在Bash脚本中如何转义空格

4

我正在尝试编写一个脚本来将所有以.hash结尾的文件追加到md5deep进行验证。文件名中带有空格的文件似乎会破坏这个脚本。

#!/bin/bash
XVAR=""
for f in *.hash
do
    XVAR="$XVAR -x $f "
done
md5deep -e $XVAR -r *

每当我运行一个名为“O S.hash”的文件的脚本时,就会出现以下情况:
O: No such file or directory

如果我将 XVAR="$XVAR -x $f " 改为 XVAR="$XVAR -x \'$f\' " 或者 XVAR="$XVAR -x \"$f\" "

md5deep 会将输入解释为 "O 而非预期的字符串。

"O: No such file or directory

脚本中变量的回显显示XVAR为-x 'O S.hash'-x "O S.hash"

在shell中手动输入命令,如md5deep -e -x "O S.hash" -r *可以工作,但如果在脚本中,则该命令似乎会出错。

2个回答

3
这不是最好的解决方案,但似乎可以工作:
find . -name '*.hash' -printf "-x\0%p\0" | xargs -0 md5deep -r * -e

实际上这并不完全符合原帖作者的要求,所以根据Tim Pote和Jonathan Leffler的建议进行了修改:

find . -maxdepth 1 -name '*.hash' -printf "-x\0%p\0" | xargs -0 md5deep -r * -e

如果存在包含“.hash”文件的子目录,则会导致在命令行上列出多余的文件。 - Jonathan Leffler

2
现在你知道为什么Unix系统上的人们传统上避免使用带空格的文件名(以及目录名)-编写程序让shell处理这些名称很麻烦(委婉地说)。 shell是为没有这种名称的系统设计的。 换行符也会引起很多问题。
使用bash,到目前为止,最好的解决方案是使用数组来保存元素,然后使用“${array[@]}”将它们列出来; 这几乎是微不足道的:
declare -a XVAR

for file in *.hash
do
    XVAR+=("-x" "$file")
done

md5deep -e "${XVAR[@]}" -r *

利用Gordon Davisson提到的数组扩展符号。请参阅Bash参考手册(适用于Bash 4.1)第6.7节“数组”以获取大量有关数组信息;请参阅第3.4节“Shell参数”以获取+=运算符的信息。
如果由于某种原因无法使用数组,则需要编写一个程序来转义其参数,以便shell不会扭曲它们。我有这样一个程序,名为“escape”。
XVAR=
for file in *.hash
do
    name=$(escape "$file")
    XVAR="$XVAR -x $file"
done
eval md5deep -e $XVAR -r *

使用eval函数有些棘手;它可以工作,但最好使用数组。

1
这里有一种更简单的方法来向数组添加条目:XVAR+=(-x "$file") - Gordon Davisson
啊,谢谢@GordonDavisson;我知道我肯定是忽略了什么,但我不确定是什么!Bash(4.1)参考手册中的数组部分(§6.7)没有提到+=;当你知道你需要寻找+=时,你可以在§3.4中找到这个符号,并且那里也提到了数组的行为。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接