你是对的,/ 无效,空字节 \0 也是如此。没有办法绕过这个限制(除了文件系统黑客)。
文件名中可以使用所有其他字符,包括换行符\n 或制表符\t 等令人惊讶的字符。输入它们的方法有很多,因此 shell 不会将它们理解为特殊字符。我只会给出一个务实的方法。
您可以输入大多数可打印字符,方法是使用单引号' 来引用它们:
date > 'foo!bar["#$%&()*+,-.:;<=>?@[\]^_`{|}~'
当然,您不能以这种方式输入单引号,但为此您可以使用双引号":
date > "foo'bar"
如果你需要两者都有,你可以结束一个引用并开始另一个:
date > "foo'bar"'"bloh'
您也可以使用反斜杠\ 直接转义特殊字符:
date > foo\"bar
反斜杠也可以用作带有双引号的转义符,它在单引号中不起作用(它是一个没有特殊含义的简单字符)。
如果需要输入换行等不可打印的字符,可以使用美元单引号:
date > $'foo\nbar'
这在 bash 中有效,但不一定在所有其他 shell 中。所以保重!
最后,使用变量来保存你的奇怪名字是有意义的(为了不必直接拼出来:
strangeName=$(xxd -r <<< "00 41 42 43 ff 45 46")
date > "$strangeName"
这样可以保持 shell 代码的可读性。
但是一般来说,在文件名中包含这样的字符并不是一个好主意,因为很多脚本无法正确处理这样的文件。
编写万无一失的脚本并不容易。最基本的规则是双引号中的引号变量用法:
for i in *
do
cat "$i" | wc -l
done
这将解决您可能遇到的 99% 的问题。
如果您使用find 查找可以包含特殊字符的目录条目,您应该使用printf0 来分隔输出,而不是空格而是空字节。 xargs 等其他程序通常可以理解以空字节分隔的文件名列表。
如果您的文件名可以以破折号- 开头,则通常会被误认为是一个选项。一些程序允许提供特殊选项-- 来声明所有后续参数都不是选项。更通用的方法是使用不以破折号开头的名称:
for i in *
do
cat ./"$i" | wc -l
done
这样,名为-n 的文件将不会运行cat -n,而是运行cat ./-n,这不会被理解为-n 赋予cat 的选项(这意味着“数字行”)。