这是您可能熟悉的问题:我想查询我的Mac上的磁盘使用情况,所以我在我的主目录中尝试了
~/$> for file in `ls`; do du -hs $file; done
带输出
55M Applications
107M Desktop
132G Documents
5.1G Downloads
16G Library
457M Music
53M Pictures
du: VirtualBox: No such file or directory
du: VMs: No such file or directory
除了最后一个之外很棒,因为它是一个名为“VirtualBox VMs”的目录 - 名称中有一个空格。我谷歌它(实际上,我所要做的就是开始输入“bash loop ...”并且它自动完成“用空格覆盖文件循环” - 感谢Google!)我得到了这个问题,Iterate over list of files with spaces ,作为第一个结果。
如果你仔细阅读那个帖子,你会发现很多复杂的解决方案使用xargs
或者奇怪的东西。当然,我可以编写自己的函数来处理这些情况,但我非常坚持有一个单行解决方案。因此,在我看来,最好的解决方案(虽然不是最高投票或被接受的解决方案)是
for file in *; do du -hs "${file}"; done
有些反常,以下不起作用:
删除引号
for file in *; do du -hs ${file}; done #splits on spaces and throws error
使用ls
,即使是引号:
for file in `ls`; do du -hs "${file}"; done #splits on spaces and throws error
我的问题是,一些bash专家可以准确地向我解释所有这些之间的区别是什么,以及为什么失败的失败?
答案 0 :(得分:1)
意识到工作案例扩展为:du -hs "VirtualBox VMs"
。
对于这种情况,问题是该命令扩展为:
du -hs VirtualBox VMs
这会将两个文件名传递给du
命令。
对于这种情况,问题是for
命令看到两个单独的标记。因此,迭代迭代迭代每个
du -hs VirtualBox
du -hs VMs
答案 1 :(得分:0)
这一切都解释了在进程替换和参数扩展之后发生分词的事实。因此,$(ls)
和${file}
的结果会进行分词,而"${file}"
中的双引号则会抑制分词。