我正在开始 bash 脚本编写,但无法处理空格文件名。我在这里搜索了有关我的问题的其他问题,例如:
how to output file names surrounded with quotes in SINGLE line?
在我的脚本中,我需要获取所有目录,最后每个目录都做一些工作。所以我的脚本的骨架是:
for directory in `find "$DIR" -type d`
do
# ... some work ...
done
此脚本不适用于带空格的文件名。所以我尝试将 find 与 exec 结合使用,这似乎是一个优雅且简单的解决方案,但没有任何改变。更准确地说,我尝试过:
(I) find "$DIR" -type d -exec echo -n '"{}" ' \;
(II) find "$DIR" -type d -exec echo -n '"{}" ' +
在使用命令 -exec 之前,我读了一些相关内容,但我仍然不清楚,所以:
- 什么是以及如何工作 '"{}"'\;
- “{}”的作用和工作原理 +
- 如何修复脚本中的空格文件名?
最佳答案
What's and how works '"{}" ' \;
对于每个文件名,这基本上都会执行 echo -n "\"filename\""
,生成一堆类似 "filename"
的行。
添加文字引号并没有帮助,因为 bash 不会开始将数据解释为 shell 脚本代码。
如果你读到 foo; ls $foo
,您不能只输入 $(rm/)
来运行命令,也不能只输入 "foo bar"
> 以避免分割文件名。数据就是数据,而不是代码,并且不尊重 shell 语法。
What's and how works '"{}" ' +
+
对一组文件名运行一次命令(为了提高效率,而不是一次运行一个)。由于替换的工作方式,它与 {} +
相同,因为参数只是被删除并替换为一堆文件名。
How can i fix my script also for spaced filename?
只需使用 IFS
变量更改 bash 用于拆分的字符,即可使其在 95% 的情况下正常工作:
IFS=$'\n'
for dir in $(find "$DIR" -type d)
do
echo "Directory: >> $dir <<"
done
这使得 bash 仅在换行符上进行分割,而不是默认的所有空白(这可能会对代码的其余部分产生一些有趣的副作用,因此您可能需要在之后将 IFS 的值设置回其原始值)。
文件名也可以包含换行符。最好的方法是使用:
while IFS= read -d '' -r dir
do
echo "Directory: >> $dir <<"
done < <(find "$DIR" -type d -print0)
这使得find
输出文件被NUL字节分割,文件名永远不能包含该文件。
关于bash - 理解(多重和自动)文件名引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15752688/