我正在尝试编写一个bash脚本来列出当前目录的每个文件/子目录的大小,如下所示:
for f in $(ls -A)
do
du -sh $f
done
我使用了ls -A
,因为我需要包含以点开头的隐藏文件/目录,例如.ssh
。但是,如果$f
中的文件名包含空格,则上述脚本无法处理空格。
例如我有一个名为:
books to borrow.doc
以上脚本将返回:
du: cannot access `books': No such file or directory
du: cannot access `to': No such file or directory
du: cannot access `borrow.doc': No such file or directory
有一个类似的问题Shell script issue with filenames containing spaces,但要处理的名称列表来自展开*
(而不是ls -A
)。该问题的答案是向$f
添加双引号。我尝试了相同的,即改变
du -sh $f
到
du -sh "$f"
但结果是一样的。我的问题是如何编写脚本来处理空格?
感谢。
答案 0 :(得分:3)
不要解析ls
的输出。当文件包含空格时,$f
包含在空格上分割的文件名的部分,因此双引号没有得到整个文件名
下一个将工作,并将与您的脚本
相同GLOBIGNORE=".:.." #ignore . and ..
shopt -s dotglob #the * will expand all files, e.g. which starting with . too
for f in *
do
#echo "==$f=="
du -sh "$f" #double quoted (!!!)
done
答案 1 :(得分:2)
除非目录太大,文件名列表太大:
du -sh * .*
请注意,这将包括.
和..
。如果你想消除..
(可能是一个好主意),你可以使用:
for file in * .*
do
[ "$file" = ".." ] && continue
du -sh "$file" # Double quotes important
done
您可以考虑将名称分配给数组,然后处理数组:
files=( * .* )
for file in "${files[@]}"
do
...
done
您可以使用其中的变体来对名称组运行du
,但您也可以考虑使用:
printf "%s\0" "${files[@]}" | xargs -0 du -sh
答案 2 :(得分:1)
如果find
循环会导致头痛,我通常更喜欢使用程序for
。在你的情况下,它非常简单:
$ find . -maxdepth 1 -exec du -sh '{}' \;
使用-exec
存在许多安全问题,这就是为什么GNU find
支持更安全的-execdir
,如果可用的话,应该首选find
。由于我们不是在这里递归到目录,但它并没有产生真正的区别。
-print0
的GNU版本还有一个选项({{1}})来打印出由NUL字节分隔的匹配文件名,但我发现上述解决方案比先输出一个更简单(也更有效)列出所有文件名,然后将其拆分为NUL字节,然后迭代它。
答案 3 :(得分:0)
试试这个:
ls -A |
while read -r line
do
du -sh "$line"
done
while循环逐行检查,而不是逐字检查ls -A
输出。
这样,您就不需要更改IFS变量。
答案 4 :(得分:0)
总结时间。假设您正在使用Linux,这应该适用于大多数(如果不是全部)情况。
find -maxdepth 1 -mindepth 1 -print0 | xargs -r -0 du -sh