我正在编写一个脚本,要求我提供目录中的文件列表,其文件名包含空格、*、?、$、% 等。我该怎么做,我看过很多帖子,但找不到任何适合我的东西。使用 grep 可以实现这一点吗?
答案1
printf '<%s>\n' *[[:space:]*?$%]*
它不会报告隐藏文件。是否[[:space:]]
匹配多字节间距字符(如" "
(电磁四元组)在 UTF-8 中)取决于您的 shell(有些还dash
不能识别多字节字符)
例子:
$ touch sane 'a%b' $'with\nnewline' $'with space' $'with em-quad'
$ printf '<%s>\n' *[[:space:]*?$%]*
<a%b>
<with em-quad>
<with
newline>
<with space>
答案2
*
使用不带引号的, 不使用 find生成文件的安全列表:
$ echo *
让我们有一些文件来测试:
$ mkdir test-dir; cd test-dir
$ touch clean normal_file 'a%b' 'has two spaces' '*' 'a*b' '?' 'a?b'
$ touch '$' 'a$b' '%' 'a%b' $'new\nline' $'em\u2001quad' 'normal_file'
该echo *
命令将生成上述文件:
? $ * % a?b a$b a*b a%b clean em quad has two spaces new
line normal_file
由空格分隔的列表,是的,有两行,因为有一个文件名称中包含换行符。
查看文件的一种更简单的方法是引用它们的名称printf '%q'
并添加新行,就像printf '%q\n'
我们得到一个干净的文件列表一样:
$ printf '%q\n' *
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
clean
$'em\342\200\201quad'
has\ two\ spaces
$'new\nline'
normal_file
当然,您需要选择一些文件,而不是全部,就像普通的 *.
因此,我们创建一个所有要匹配的字符的模式:?$*%
。
然而,大多数这些字符都是“特殊”的,当出现在某些命令中时需要引用。具体来说,如果*
或?
跟随$
,它们会被 shell 扩展,这可能会产生问题。
必须引用$
.
然后,获取所有其他字符被引用的简单方法是使用printf '%q' ?\$*%
.这将产生:\?\$\*%
。如果不是严格需要反斜杠,则不会产生不良影响,转义字符仍然有效。
我们需要向该列表添加一些空白字符。但新线的加入成为一个严重的问题。在字符类中处理换行符的最简单方法是使用[[:space:]]
,它将包括换行符、空格、制表符和一些其他空格字符(如长破折号)。
因此,命令变为:
$ printf '%q\n' *[\?\$\*%[:space:]]*
\?
\$
\*
%
a\?b
a\$b
a\*b
a%b
$'em\342\200\201quad'
has\ two\ spaces
$'new\nline'
请注意,clean
和normal_file
文件名未按要求列出。
答案3
grep -E
应该做你需要的。请注意,某些字符需要使用反斜杠进行转义,因此如果您添加更多字符并且结果不是您所期望的,请对其进行转义并重试。请注意,这|
是一个or
...
$ ls | grep -E '\s|\*|\?|\$|%'
all this.txt
all?this.txt
all*this.txt
all%this.txt
all th*s.txt
all$.txt
答案4
这非常简单,并且从 1979 年起就已经可以在 Bourne Shell 中使用:
for i in *
do
case "$i" in
*\ *) echo blank $i;;
*\?*) echo qmark $i;;
esac
done
一行:
for i in *; do
case $i in
*\ *|*\?*|*\**|*\$*|*%* ) echo "Special character $i"; ;;
* ) echo "normal file $i"; ;;
esac
done
如果您愿意,可以添加更多案例...