我应该在bash脚本中使用哪些技术或原则来处理允许包含尽可能多的目录和文件名
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
和空间?
我猜/
在大多数linux / unix系统中不是有效的文件名或目录名字符?
到目前为止,我在!
,;
,|
,(空格字符)和
'
文件名方面遇到了问题。
答案 0 :(得分:3)
你是对的,/
无效,空字节\0
也是如此。没有办法解决这个限制(除了文件系统黑客攻击)。
所有其他字符都可以在文件名中使用,包括作为换行符\n
或标签\t
等令人惊讶的字符。有很多方法可以输入它们,以便shell不会将它们理解为特殊字符。我会采取务实的态度。
您可以使用单引号'
输入大多数可打印的字符来引用它们:
date > 'foo!bar["#$%&()*+,-.:;<=>?@[\]^_`{|}~'
当然,您不能以这种方式输入单引号,但为此您可以使用双引号"
:
date > "foo'bar"
如果你需要两者兼而有之,你可以结束一个引用并开始另一个引用:
date > "foo'bar"'"bloh'
或者您也可以使用反斜杠\
直接转义特殊字符:
date > foo\"bar
反斜杠也可以作为具有双引号的转义器,它在单引号内不起作用(这是一个没有特殊含义的简单字符)。
如果您需要输入不可打印的字符(如换行符),则可以使用dollar-singlequote表示法:
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
的{{1}}选项{将意为“数字线”)。
答案 1 :(得分:0)
始终引用您的变量替换。即不是cp $source $target
,而是cp "$source" "$target"
。这样他们就不会受到分词和路径扩展的影响。
在文件操作命令的位置参数之前指定“ - ”。即不是cp "$source" "$target"
,而是cp -- "$source" "$target"
。这可以防止以dash作为选项解释文件名。
是的,“/”不是文件/目录名称的有效字符。