如何使用命令行获取目录中的文件数?

Bla*_*ake 278 command-line

我有一个包含大量文件的目录。我没有看到ls提供计数的开关。是否有一些命令行魔术来获取文件数?

小智 353

使用“文件”的广义定义

ls | wc -l
Run Code Online (Sandbox Code Playgroud)

(请注意,它不计算隐藏文件并假定文件名不包含换行符)。

要包含隐藏文件(.和除外..)并避免换行符出现问题,规范方法是:

find . ! -name . -prune -print | grep -c /
Run Code Online (Sandbox Code Playgroud)

或者递归:

find .//. ! -name . -print | grep -c //
Run Code Online (Sandbox Code Playgroud)

  • `wc` 是一个“字数统计”程序。`-l` 开关会导致它计算行数。在这种情况下,它计算`ls` 输出中的行数。这也是我一直被教导获取给定目录的文件计数的方式。 (31认同)
  • 请注意,如果输出是管道,`ls` 会执行 `ls -1`。 (29认同)
  • 这并没有把所有东西都放在一个目录中——你错过了点文件,也收集了几行额外的行。空目录仍将返回 1 行。如果你调用`ls -la`,你会在目录中得到三行。你想要`ls -lA | wc -l` 跳过 `.` 和 `..` 条目。但是,您仍然会一对一。 (6认同)
  • 一种更正的方法,即不会重复计算名称中带有换行符的文件,它是这样的:`ls -q | wc -l` - 但请注意,这种方法仍然不会计算隐藏文件,并且会计算目录。 (2认同)

Mac*_*tka 43

对于文件的狭义定义:

 find . -maxdepth 1 -type f | wc -l
Run Code Online (Sandbox Code Playgroud)

  • 一个更正的方法,不会重复计算名称中带有换行符的文件,它是这样的:`find -maxdepth 1 -type f -printf "\n" | wc -l` (9认同)

小智 20

ls -1 | wc -l
Run Code Online (Sandbox Code Playgroud)

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line
Run Code Online (Sandbox Code Playgroud)

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts
Run Code Online (Sandbox Code Playgroud)

PS:注意 ls -<number-one> | wc -<字母-l>

  • 当输出到管道时,大多数版本的 `ls` 会自动执行 `-1`。 (13认同)
  • 我+编辑了这个版本,因为它更明确。不过,是的 ls 确实使用 -1 如果它是通过管道传输的(尝试一下:ls | cat),我发现 -1 语法更明确。 (4认同)
  • @Dennis,这很有趣,我不知道应用程序可以告诉它的输出将进入管道。 (3认同)
  • @xenoterracide:在 Bash 中:`[[ -p /dev/stdin ]] &amp;&amp; echo "stdin is from a pipe"` (3认同)
  • 在我的测试中,还提供 -f 选项以避免 ls 对文件名进行排序要快得多。不幸的是,如果您的文件名包含换行符,您仍然会得到错误的答案。 (2认同)

krl*_*mlr 17

我发现它du --inodes很有用,但我不确定du它需要哪个版本。它应该比使用find和 的替代方法快得多wc

在 Ubuntu 17.10 上,以下工作:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most
Run Code Online (Sandbox Code Playgroud)

结合使用| sort -nr以按包含 inode 的数量降序排序。


Fra*_*rax 16

使用ls/ wcpair的最完整答案可能是

ls -Aq | wc -l
Run Code Online (Sandbox Code Playgroud)

如果你想计算点文件,和

ls -q | wc -l
Run Code Online (Sandbox Code Playgroud)

除此以外。

  • -A是计算点文件,但省略...
  • -qmakels用 替换非图形字符,特别是换行符?,使每个文件输出 1 行

要从lsin 终端获得单行输出(即不将其通过管道输入wc),-1必须添加选项。

ls使用 coreutils 8.23 测试的行为)

  • 正如您所说,不需要`-1`。至于 _"它通过控制台输出明智地处理文件名中的换行符"_,这是因为 `-q` 开关(你应该使用它而不是 `-b`,因为它是可移植的)它 _"强制每个非-可打印的文件名字符和 &lt;tab&gt; 字符作为 &lt;question-mark&gt; ( '?' ) 字符写入。如果输出到终端设备,实现可能会默认提供此选项。”_ 因此,例如 `ls -Aq | wc -l` 来计算所有文件/目录或 `ls -qp | grep -c /` 只计算非隐藏目录等... (2认同)

Gil*_*il' 9

如果您知道当前目录至少包含一个非隐藏文件:

set -- *; echo "$#"
Run Code Online (Sandbox Code Playgroud)

这显然可以推广到任何 glob。

在脚本中,这有时会带来覆盖位置参数的不幸副作用。您可以通过使用子 shell 或使用函数(Bourne/POSIX 版本)来解决这个问题,例如:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是$(ls -d -- * | wc -l)。如果 glob 是*,则命令可以缩短为$(ls | wc -l). 解析 的输出ls总是让我感到不安,但只要您的文件名不包含换行符,或者您对ls它们进行转义,它就应该可以工作。并且$(ls -d -- * 2>/dev/null | wc -l)具有优雅地处理不匹配 glob 情况的优点(即,在这种情况下它返回 0,而该set *方法需要繁琐地测试 glob 是否可能为空)。

如果文件名可能包含换行符,另一种方法是使用$(ls -d ./* | grep -c /).

如果有很多匹配的文件,任何依赖于将 glob 的扩展传递给的解决方案都ls可能因参数列表太长错误而失败。


aud*_*ude 7

find -maxdepth 1 -type f -printf . | wc -c
Run Code Online (Sandbox Code Playgroud)
  • -maxdepth 1将使它成为非递归的,find默认是递归的
  • -type f 将仅包含文件
  • -printf .是可爱的触感。它为每个文件打印一个点而不是文件名,现在它能够处理任何文件名并保存数据;我们只需要数点:)
  • | wc -c 计数字符


小智 5

在使用 ls/wc 对时,如果我们添加 -U 它将快得多(不要排序)。

ls -AqU | wc -l
Run Code Online (Sandbox Code Playgroud)

  • `-U` 是特定于 GNU 的。 (2认同)