我正在查看一些旨在获取目录中文件数的 shell 代码。内容如下:
COUNT=$(ls -1 ${DIRNAME} | wc -l)
-1
部分是什么意思?我在任何其他问题中找不到任何关于此的信息,只是传递对迭代目录中文件的引用,这不是我正在查看的目录。此外,从命令中删除它似乎没有任何效果。
最佳答案
COUNT=$(ls -1 ${DIRNAME} | wc -l)
...是计算目录中文件数量的错误方法:ls -1
告诉 ls
不要将多个文件放在一行;确保 wc -l
将通过计算行数来计算文件数。
现在,让我们谈谈“ buggy ”:
- 文件名可以包含文字换行符。
ls
的一个版本如何处理这个是实现定义的;有些版本可能会重复计算此类文件(GNU 系统不会,但我不想打赌,比如说,随机发布的busybox
在嵌入式路由器上 float )。 ${DIRNAME}
的未加引号扩展允许目录名称在传递给ls
之前进行字符串拆分和全局扩展,因此如果名称包含空格,它可以成为多个参数。这应该是"$DIRNAME"
或"${DIRNAME}"
。
...此外,这是低效的,因为它会调用多个外部工具(ls
和 wc
)来执行 shell 可以在内部管理的操作。
如果您想要更健壮的东西,这个版本将适用于所有 POSIX shell:
count_entries() { set -- "${1:-.}"/*; if [ -e "$1" ]; then echo "$#"; else echo 0; fi; }
count=$(count_entries "$DIRNAME") ## ideally, DIRNAME should be lower-case.
...或者,如果您希望它执行得更快(不需要子 shell),请参阅以下内容(仅针对 bash):
# like above, but write to a named variable, not stdout
count_entries_to_var() {
local destvar=$1
set -- "${2:-.}"/*
if [[ -e "$1" || -L "$1" ]]; then
printf -v "$destvar" %d "$#"
else
printf -v "$destvar" %d 0
fi
}
count_entries_to_var count "$DIRNAME"
...或者,如果您的目标是 bash 并且不想为函数而烦恼,您可以使用数组:
files=( "$DIRNAME"/* )
if [[ -e "${files[0]}" || -L "${files[0]}" ]]; then
echo "At least one file exists in $DIRNAME"
echo "...in fact, there are exactly ${#files[@]} files in $DIRNAME"
else
echo "No files exist in $DIRNAME"
fi
最后——如果您想处理一个太大而无法放入内存的文件名列表,并且您有 GNU find
,请考虑使用它:
find "$DIRNAME" -mindepth 1 -maxdepth 1 -printf '\n' | wc -l
...这完全避免了将名称放入流中(因此生成一个流,如果选择的话,可以简单地以字节为单位测量长度而不是行数)。
关于bash - "ls -1 path"中的-1是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33445395/