假设我有一个包含以下文件/目录的目录:
google
apple
mozilla foundation # a file with spaces
browsers
Run Code Online (Sandbox Code Playgroud)
所以我想将文件移动到browsers目录中。这是我写的一个脚本:
for d in $(ls); do
if ! [ "$d" == "browsers" ]; then
mv "$d" "browsers"
fi
done
Run Code Online (Sandbox Code Playgroud)
然后,google和apple去browsers,但我得到:
mv: cannot stat 'mozilla': No such file or directory
mv: cannot stat 'foundation': No such file or directory
Run Code Online (Sandbox Code Playgroud)
显然,问题在于变量中的空格。处理这个问题的正确方法是什么?
当然,我相信应该有一个更优雅的单行命令来做到这一点,但我想知道我应该如何使用带有空格的变量。
千万不能永远使用:
for d in $(ls)
Run Code Online (Sandbox Code Playgroud)
改用这个:
for d in *
Run Code Online (Sandbox Code Playgroud)
除其他外,使用 的两个问题$(ls)是外壳将结果$(ls)归为分词和路径名扩展。在您的情况下,是分词导致 mozilla foundation变成mozilla和foundation。
有关不使用的原因的详细讨论$(ls),请参阅“有什么作用$(ls *.txt)?”
如果您需要考虑目录中没有非隐藏文件的情况(这种情况for i in $(ls)可能看起来更好,因为它没有在循环中进行任何传递,而不是在循环中使用*as $iin进行一次传递for i in *(除了在zsh)) 中,您想告诉外壳不要为不匹配的 glob 扩展到任何内容:
zsh: for i in *(N)ksh93: for i in ~(N)*bash4.4+:(f() { local -; shopt -s nullglob; for i in *; ...; done; }; f重点是在nullglob本地使用该选项(另请参阅failglob与zsh的默认行为类似的选项))。yash:(set -o nullglob然后重置,yash据我所知,没有本地范围的选项)[ -e "$i" ] || [ -L "$i" ] || continue在循环中添加 a以检查文件是否存在。