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


Answers:


239

使用“文件”的广义定义

ls | wc -l

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

为了包括隐藏文件(.和除外..)并避免换行符出现问题,规范的方式是:

find . ! -name . -prune -print | grep -c /

或递归地:

find .//. ! -name . -print | grep -c //

23
wc是一个“字数统计”程序。所述-l开关使其计数行。在这种情况下,它将对来自的输出中的行进行计数ls。这也是我一直被教如何获取给定目录的文件计数的方法。
桑迪

20
请加注意,ls确实ls -1如果输出管道。
lesmana 2010年

6
不能将所有内容都保存在目录中-您错过了点文件,还收集了一些额外的行。空目录仍将返回1行。如果调用ls -la,您将在目录中得到三行。您要ls -lA | wc -l跳过...条目。但是,您仍然会一一掉队。

1
一个空目录为我返回0
James Roth 2013年

2
一种更正的方法是,不会对名称中带有换行符的文件进行重复计数:ls -q | wc -l-尽管请注意,此方法仍不会对隐藏文件进行计数,并且会对目录进行计数。
godlygeek'3

30

对于狭窄的文件定义:

 find . -maxdepth 1 -type f | wc -l

当然,您可以省略-maxdepth 1用于递归计数文件的(或针对所需的最大搜索深度进行调整)。
user7089 2014年

1
如果您的文件名包含换行符,则此方法将错误地对其计数两次。
godlygeek'3

7
一种正确的方法是,不会重复计算名称中包含换行符的文件,它是:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek

+1允许隐藏文件并忽略目录
Michael Durrant

13
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS:注意ls-<数字一> | wc-<字母-l>


10
当输出到管道时,大多数版本的lsdo会-1自动执行。
丹尼斯·威廉姆森

3
@Dennis很有意思,我不知道一个应用程序可以告诉它输出到管道。
xenoterracide

1
我+推荐了这个版本,因为它更为明确。虽然,是的,如果通过管道将ls确实使用-1(请尝试:ls | cat),但我发现-1语法更加明确。
gabe。

3
@xenoterracide:在Bash中:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
丹尼斯·威廉姆森

2
在我的测试中,提供-f选项可以避免ls对文件名进行排序,这明显要快得多。不幸的是,如果文件名包含换行符,您仍然会得到错误的答案。
塞缪尔·埃德温·沃德

10

使用ls/ wc对,最完整的答案可能是

ls -Aq | wc -l

如果您要计算点文件,并且

ls -q | wc -l

除此以外。

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

为了从ls输入端子获得单线输出(即,不将其管道输送到wc),-1必须添加选件。

ls使用coreutils 8.23进行测试的行为)


2
如您所说,-1是不需要的。至于“它通过控制台输出明智地处理文件名中的换行符”,这是因为-q开关(您应该使用该开关,而不是-b因为它是可移植的),该开关“强制每个不可打印的文件名字符和<tab>字符的实例被写入作为<question-mark>('?')字符。如果输出是到终端设备的,则实现默认情况下可以提供此选项。” 因此,例如ls -Aq | wc -l,计算所有文件/目录或ls -qp | grep -c /仅计算非隐藏的目录等...
don_crissti 2015年

感谢您的输入。更改-b-q
Frax 2015年

7

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

set -- *; echo "$#"

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

在脚本中,这有时会覆盖位置参数,从而产生不幸的副作用。您可以通过使用子外壳或使用类似以下功能(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"

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

如果文件名可能包含换行符,则可以使用$(ls -d ./* | grep -c /)

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


1
您是否真的要创建13,923个位置参数?然后,您应该制作局部变量local或将其消除:eval $1=$#或者只是使用echo $#do即可number_of_files=$(count_words *)
丹尼斯·威廉姆森

1
@丹尼斯:部分目的是避免分叉。我想这不是21世纪的问题。好的,我承认我不再关心非POSIX外壳了,因此我可以避免使用临时变量。
吉尔斯

为什么要从中减去一个$#(在编辑之前您没有做过)?
丹尼斯·威廉姆森

@Dennis:我仍然避免使用fork(嗯,它确实在CPU速度较慢的计算机(例如路由器)上有所作为),并且将变量名传递为$1。所以我想算的是不是第一个参数的参数数量。(我不能使用,shift因为我需要保留变量名。)(嗯,现在您是否要询问第一行...)
Gilles

@丹尼斯:想一想,shift如果时间合适,我可以使用。
吉尔斯

7

我发现它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

结合| sort -nr以按包含索引节点的数量降序排序。


5

当使用ls / wc对时,如果我们添加-U,它将更快(不进行排序)。

ls -AqU | wc -l

1
-U是特定于GNU的。
斯特凡Chazelas

4

安装tree命令后,只需键入:

tree

如果您也想要隐藏文件:

tree -a

如果您使用的是Debian / Mint / Ubuntu Linux,请键入以下命令以安装tree命令:

sudo apt-get install tree

选项-L用于指定目录树的最大显示级别。tree命令不仅考虑文件的数量,还计算目录的数量,并根据需要选择任意数量的目录树。


键入tree时,我会在目录所在的屏幕上得到某种树输出,但看不到显示的文件数。
charlesdarwin

2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1将使其非递归,find默认情况下为递归
  • -type f 仅包含文件
  • -printf .很可爱 它为每个文件而不是文件名打印一个点,现在它可以处理任何文件名并保存数据。我们只需要数点:)
  • | wc -c 数字符

1

没有管道,没有字符串副本,没有叉子,只是普通的打击一个衬里

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount

1
如果目录中没有文件,则值为1。不计算文件,不计算文件和目录。
史蒂夫·

1

这是吉尔斯(Gills)发表的另一种技巧:

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

它会创建一个包含13,923个元素的数组(如果那是有多少个文件)。


c数组的意义是什么?word_count() { echo "$#"; }足够了。@Gilles解决方案的重点是将计数存储在返回的变量中,以避免必须使用命令替换(这涉及到ksh93以外的shell中的fork和pipe)。
斯特凡Chazelas

1
find . -type f -maxdepth 1 |  wc -l 

这只能列出当前目录中的文件。


find . -type f将在当前目录以及子目录中递归查找文件。
dhag

0

试试这个,希望这个答案对您有帮助

echo $((`ls -l | wc -l` -1 ))


0

改善以前给出的答案,但是这次明确地做。

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

值得注意的是,使用了一些喜欢的命令,例如tailcut。另外,请注意,默认情况下树不可用。上面的命令首先捕获有关级别1的目录的信息,然后获取tail -n 1我们目标所在的最后一行,最后得到cut第三个单词。

例如,位于/

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

然后,询问目录数又如何呢?



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.