我有以下bash脚本:
DIR="~/Folder/With Spaces"
CMD="find $DIR -type f"
# echo showing hidden characters
echo $CMD | cat -v
while read line
do
echo $line
done < <($CMD)
输出:
find ~/Folder/With Spaces -type f
find: ~/Folder/With: No such file or directory
find: Spaces: No such file or directory
我已经通过单句和双引号,反斜线,没有后斜线,在其他行中围绕其他行,没有骰子。
如果我正确理解这一点,则CMD应该是以下内容:
find ~/Folder/With Spaces -type f
这应该可以正常工作,并且由于find
无法在其路径周围使用引号,因此这是正确的方法。回声显示它与此匹配。将此字符串键入命令行的工作正常。同样,echo
命令打印此。但是脚本的输出表示还有其他事情正在发生,可能在执行命令的done
行上。
在这种情况下,我将如何使bash解释文件名为一条路径?为什么?后斜线(阻止它将其解释为被空间隔开的两个部分)被视为字符串的一部分,所以它在哪里拆分,为什么?
bash永远不会将数据评估为代码,但是它可以做一些可以使您认为确实如此的事情(即单词分开和射击)。由于是Shell语法的一部分,因此当您展开变量时,它不会重新解释为逃生序列。
这是您应该做的:
DIR=~/"Folder/With Spaces" # ~ doesn't expand in quotes, and there's no "".
CMD=(find "$DIR" -type f) # use an array to keep track of words
# Print the words escaped so you know what will actually be executed
printf "%q " "${CMD[@]}" | cat -v
echo
while IFS= read -r line # don't split or interpret words
do
echo "$line" # use quotes to prevent globbing and word splitting
done < <("${CMD[@]}") # run the command in the array without spacing issues