您是对的,/
无效, null-byte 也是如此\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
(这意味着“数字行”)。