user4556274已经回答了为什么。我的回答仅用于提供有关如何正确计数文件的其他信息。
在Unix社区中,普遍的共识是,解析文件的输出ls
是一个非常非常糟糕的主意,因为文件名可以包含控制字符或隐藏字符。例如,由于文件名中有换行符,我们ls | wc -l
告诉我们输出ls
(确实有5行),但实际上目录中只有4个文件。
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
方法1:查找实用程序
该find
命令通常用于解析文件名,它可以通过打印inode号来帮助我们。无论是目录还是文件,它都只有一个唯一的索引节点号。因此,使用-printf "%i\n"
和排除.
via -not -name "."
可以使文件数量准确。(请注意使用-maxdepth 1
来防止递归下降到子目录中)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
方法2:Globstar
简单,快速且通常可移植的方式:
$ set -- *
$ echo $#
228
set
命令用于设置外壳的位置参数($<INTEGER>
如中的变量echo $1
)。这通常用于解决/bin/sh
缺少数组的限制。可以在Unix&Linux上的Gille的答案中找到执行额外检查的版本。
在支持数组的shell中,例如bash
,我们可以使用
items=( dir/* )
echo ${#items[@]}
正如钢铁司机在评论中提出的。
与find
过去使用过的方法wc
和globstar 相似的技巧可用于stat
计算每行的索引节点数:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
另一种方法是在for
循环中使用通配符。(请注意,此测试使用不同的目录来测试此方法是否归入子目录,而子目录不会这样做-16是my中已验证的项目数~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
方法3:其他语言/口译员
Python还可以通过打印给定我os.listdir()
函数的列表长度来处理有问题的文件名(这是非递归的,并且只会列出作为参数给出的目录中的项目)。
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
也可以看看
ls | wc -l
如果文件名中包含换行符的文件将失败。这更具弹性:find . -mindepth 1 -maxdepth 1 -printf . | wc -c