如何递归计算 Linux 目录中的文件?
我找到了这个:
find DIR_NAME -type f ¦ wc -l
但是当我运行它时,它会返回以下错误。
查找:路径必须在表达式之前:¦
*
是“星号”ASCII 字符,但在某些其他上下文中是“次”。
这应该有效:
find DIR_NAME -type f | wc -l
解释:
-type f 仅包含文件。
| (而不是 ¦)将 find 命令的标准输出重定向到 wc 命令的标准输入。
wc(字数的缩写)计算其输入(文档)中的换行符、字数和字节数。
-l 只计算换行符。
笔记:
将 DIR_NAME 替换为 .在当前文件夹中执行命令。
您还可以删除 -type f 以在计数中包含目录(和符号链接)。
如果文件名可以包含换行符,则此命令可能会过度计数。
解释为什么您的示例不起作用:
在您显示的命令中,您不使用“管道”(|
)来连接两个命令,而是使用 shell 无法识别为命令或类似内容的断线(¦
)。这就是您收到该错误消息的原因。
对于当前目录:
find -type f | wc -l
.
find .
如果您想了解当前目录下每个目录中有多少文件:
for i in */ .*/ ; do
echo -n $i": " ;
(find "$i" -type f | wc -l) ;
done
当然,这可以全部放在一条线上。括号阐明了应该监视谁的输出 wc -l
(在本例中为 find $i -type f
)。
find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' i ; do
可以修复它。请参阅How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
find
用于外部循环只是一个不必要的复杂化。 for i in */
;做`
在我的计算机上,在接受的答案中,rsync
比 find | wc -l
快一点:
$ rsync --stats --dry-run -ax /path/to/dir /tmp
Number of files: 173076
Number of files transferred: 150481
Total file size: 8414946241 bytes
Total transferred file size: 8414932602 bytes
第二行包含文件数,在上面的示例中为 150,481。作为奖励,您还可以获得总大小(以字节为单位)。
评论:
第一行是文件、目录、符号链接等的计数,这就是它比第二行大的原因。
--dry-run(或简称 -n)选项对于不实际传输文件很重要!
我使用 -x 选项来“不跨越文件系统边界”,这意味着如果你为 / 执行它并且你连接了外部硬盘,它只会计算根分区上的文件。
find ~ -type f | wc -l
花费了 1.7/0.5/1.33 秒(真实/用户/系统)。 rsync --stats --dry-run -ax ~ /xxx
耗时 4.4/3.1/2.1 秒。这适用于 SSD 上大约 500,000 个文件。
Number of files: 487 (reg: 295, dir: 192)
rsync version 2.6.9 protocol version 29
您可以使用
$ tree
安装树包后
$ sudo apt-get install tree
(在 Debian / Mint / Ubuntu Linux 机器上)。
该命令不仅显示文件数,还分别显示目录数。选项 -L 可用于指定最大显示级别(默认情况下,它是目录树的最大深度)。
通过提供 -a
选项也可以包含隐藏文件。
-a
选项才能包含它们。
brew
并运行 brew install tree
,最好在运行 brew update
之后。
由于 UNIX 中的文件名可能包含换行符(是的,换行符),wc -l
可能会计算太多文件。我会为每个文件打印一个点,然后计算点数:
find DIR_NAME -type f -printf "." | wc -c
注意:-printf
选项仅适用于来自 GNU findutils 的 find。您可能需要安装它,例如在 Mac 上。
find
。在 OSX 上,您需要安装 GNU Find,例如 brew install findutils
。
将这里的几个答案结合在一起,最有用的解决方案似乎是:
find . -maxdepth 1 -type d -print0 |
xargs -0 -I {} sh -c 'echo -e $(find "{}" -printf "\n" | wc -l) "{}"' |
sort -n
它可以处理奇怪的事情,例如包含空格括号甚至换行的文件名。它还按文件数对输出进行排序。
您可以增加 -maxdepth
之后的数字来计算子目录。请记住,这可能需要很长时间,特别是如果您有一个高度嵌套的目录结构和一个高 -maxdepth
数字。
echo -e
是怎么回事?我猜你把它放进去折叠任何换行符,但它也会破坏任何其他不规则的空格,并尝试扩展文件名中逐字出现的任何通配符。我会简单地使用 find .* * -type d -execdir sh -c 'find . -type f -printf "\n" | wc -l; pwd'
之类的东西并忍受输出中的任何异常,或者可以使用 Bash 的 printf "%q"
来打印目录名称。
如果您想知道当前工作目录中存在多少文件和子目录,您可以使用此单行
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find {} | wc -l) {}' | sort -n
这将适用于 GNU 风格,并且只需从 BSD linux(例如 OSX)的 echo 命令中省略 -e。
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find "{}" | wc -l) "{}"' | sort -n
find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo $(find {} | wc -l) \\t {}' | sort -rn | less
echo -e
(或者只是前面评论中的 `echo`)会以一个问题换另一个问题。
您可以使用命令 ncdu
。它将递归地计算一个 Linux 目录包含多少个文件。这是一个输出示例:
https://i.stack.imgur.com/18IP1.png
它有一个进度条,如果您有很多文件,这很方便:
https://i.stack.imgur.com/gNKff.gif
在 Ubuntu 上安装它:
sudo apt-get install -y ncdu
基准测试:我使用 https://archive.org/details/cv_corpus_v1.tar(380390 个文件,11 GB)作为必须计算文件数量的文件夹。
寻找 。 -类型 f | wc -l:大约 1 分 20 秒完成
ncdu:大约 1m20s 完成
find . -type f | wc -l
和 ncdu
之间有任何区别。
find
在后台执行与 du
或多或少相同的系统调用,du
是 ncdu
的后端。只是跟踪他们。
如果您需要递归计算特定文件类型,您可以执行以下操作:
find YOUR_PATH -name '*.html' -type f | wc -l
-l
只是显示输出中的行数。
如果您需要排除某些文件夹,请使用 -not -path
find . -not -path './node_modules/*' -name '*.js' -type f | wc -l
tree $DIR_PATH | tail -1
样本输出:
5309 个目录,2122 个文件
cut -d',' -f2
进行管道传输。
如果您想避免错误情况,请不要让 wc -l
查看带有换行符的文件(这将被视为 2+ 个文件)
例如,假设我们有一个文件,其中包含一个 EOL 字符
> mkdir emptydir && cd emptydir
> touch $'file with EOL(\n) character in it'
> find -type f
./file with EOL(?) character in it
> find -type f | wc -l
2
由于至少 gnu wc
似乎没有读取/计数空终止列表(文件除外)的选项,因此最简单的解决方案就是不传递文件名,而是每次文件都传递静态输出找到,例如在与上述相同的目录中
> find -type f -exec printf '\n' \; | wc -l
1
或者,如果您的 find
支持它
> find -type f -printf '\n' | wc -l
1
要确定当前目录中有多少文件,请输入 ls -1 | wc -l
。这使用 wc
对 ls -1
的输出中的行数 (-l)
进行计数。它不计算点文件。请注意,我在本 HOWTO 的先前版本中使用的 ls -l
(这是一个“L”而不是前面示例中的“1”)实际上会给你一个比实际计数大一的文件计数。感谢 Kam Nejad 的这一点。
如果你只想计算文件而不包括符号链接(只是你可以做的一个例子),你可以使用 ls -l | grep -v ^l | wc -l
(这次是“L”而不是“1”,我们想要一个“long”在这里列出)。 grep
检查任何以“l”开头的行(表示链接),并丢弃该行 (-v)。
相对速度:“ls -1 /usr/bin/ | wc -l”在卸载的 486SX25 上大约需要 1.03 秒(这台机器上的 /usr/bin/ 有 355 个文件)。 “ls -l /usr/bin/ | grep -v ^l | wc -l
”大约需要 1.19 秒。
来源:http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x700.html
ls -l
必须对每个文件执行 stat
系统调用以读取其大小、mtime 和其他属性,这很慢。在大目录(100.000+ 个文件)上运行 ls -l
可能需要几分钟时间。所以只计算文件,总是使用 ls -1 | wc -l
。
ls -1
在大目录中仍然会很慢,因为它必须对文件进行排序。只需 printf '%s\n' *
做同样的事情,并避免外部 ls
调用(无论如何都是 problematic),但最有效的解决方案是使用不执行任何排序的命令,例如 find
。 (glob 输出按 shell 排序。)
使用 bash:
使用 ( ) 创建一个条目数组并使用 # 获取计数。
FILES=(./*); echo ${#FILES[@]}
好的,这不会递归地计算文件,但我想先展示简单的选项。一个常见的用例可能是创建文件的翻转备份。这将创建 logfile.1、logfile.2、logfile.3 等。
CNT=(./logfile*); mv logfile logfile.${#CNT[@]}
启用 bash 4+ globstar
的递归计数(如@tripleee 所述)
FILES=(**/*); echo ${#FILES[@]}
要递归地获取文件数,我们仍然可以使用 find 以相同的方式。
FILES=(`find . -type f`); echo ${#FILES[@]}
**/*
进行递归枚举。它在大型目录上的效率仍然低于 find
,因为 shell 必须对每个目录中的文件进行排序。
对于名称中带有空格的目录...(基于上面的各种答案)-递归打印目录名称以及其中的文件数:
find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
示例(为便于阅读而格式化):
pwd
/mnt/Vancouver/Programming/scripts/claws/corpus
ls -l
total 8
drwxr-xr-x 2 victoria victoria 4096 Mar 28 15:02 'Catabolism - Autophagy; Phagosomes; Mitophagy'
drwxr-xr-x 3 victoria victoria 4096 Mar 29 16:04 'Catabolism - Lysosomes'
ls 'Catabolism - Autophagy; Phagosomes; Mitophagy'/ | wc -l
138
## 2 dir (one with 28 files; other with 1 file):
ls 'Catabolism - Lysosomes'/ | wc -l
29
使用 tree
可以更好地显示目录结构:
tree -L 3 -F .
.
├── Catabolism - Autophagy; Phagosomes; Mitophagy/
│ ├── 1
│ ├── 10
│ ├── [ ... SNIP! (138 files, total) ... ]
│ ├── 98
│ └── 99
└── Catabolism - Lysosomes/
├── 1
├── 10
├── [ ... SNIP! (28 files, total) ... ]
├── 8
├── 9
└── aaa/
└── bbb
3 directories, 167 files
man find | grep mindep
-mindepth levels
Do not apply any tests or actions at levels less than levels
(a non-negative integer). -mindepth 1 means process all files
except the starting-points.
ls -p | grep -v /
(下文使用)来自 https://unix.stackexchange.com/questions/48492/list-only-regular-files-but-not-directories-in-current-directory 的答案 2
find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Catabolism - Lysosomes: 28
./Catabolism - Lysosomes/aaa: 1
应用程序:我想在数百个目录中找到最大文件数(所有深度 = 1)[下面的输出再次格式化以提高可读性]:
date; pwd
Fri Mar 29 20:08:08 PDT 2019
/home/victoria/Mail/2_RESEARCH - NEWS
time find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done > ../../aaa
0:00.03
[victoria@victoria 2_RESEARCH - NEWS]$ head -n5 ../../aaa
./RNA - Exosomes: 26
./Cellular Signaling - Receptors: 213
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Stress - Physiological, Cellular - General: 261
./Ancient DNA; Ancient Protein: 34
[victoria@victoria 2_RESEARCH - NEWS]$ sed -r 's/(^.*): ([0-9]{1,8}$)/\2: \1/g' ../../aaa | sort -V | (head; echo ''; tail)
0: ./Genomics - Gene Drive
1: ./Causality; Causal Relationships
1: ./Cloning
1: ./GenMAPP 2
1: ./Pathway Interaction Database
1: ./Wasps
2: ./Cellular Signaling - Ras-MAPK Pathway
2: ./Cell Death - Ferroptosis
2: ./Diet - Apples
2: ./Environment - Waste Management
988: ./Genomics - PPM (Personalized & Precision Medicine)
1113: ./Microbes - Pathogens, Parasites
1418: ./Health - Female
1420: ./Immunity, Inflammation - General
1522: ./Science, Research - Miscellaneous
1797: ./Genomics
1910: ./Neuroscience, Neurobiology
2740: ./Genomics - Functional
3943: ./Cancer
4375: ./Health - Disease
sort -V
是自然排序。 ...因此,我在这些(Claws Mail)目录中的最大文件数是 4375 个文件。如果我左填充(https://stackoverflow.com/a/55409116/1904943)这些文件名——它们在每个目录中都以数字命名,从 1 开始——并且填充到 5 个总数字,我应该没问题。
附录
查找目录中文件、子目录的总数。
$ date; pwd
Tue 14 May 2019 04:08:31 PM PDT
/home/victoria/Mail/2_RESEARCH - NEWS
$ ls | head; echo; ls | tail
Acoustics
Ageing
Ageing - Calorie (Dietary) Restriction
Ageing - Senescence
Agriculture, Aquaculture, Fisheries
Ancient DNA; Ancient Protein
Anthropology, Archaeology
Ants
Archaeology
ARO-Relevant Literature, News
Transcriptome - CAGE
Transcriptome - FISSEQ
Transcriptome - RNA-seq
Translational Science, Medicine
Transposons
USACEHR-Relevant Literature
Vaccines
Vision, Eyes, Sight
Wasps
Women in Science, Medicine
$ find . -type f | wc -l
70214 ## files
$ find . -type d | wc -l
417 ## subdirectories
这里有很多正确的答案。这是另一个!
find . -type f | sort | uniq -w 10 -c
其中 .
是要查看的文件夹,10
是目录分组所依据的字符数。
这种过滤格式的替代方法会计算所有可用的 grub 内核模块:
ls -l /boot/grub/*.mod | wc -l
查找-type f | wc -l
或(如果目录是当前目录)
寻找 。 -类型 f | wc -l
这将完全正常。简单的短。如果要计算文件夹中存在的文件数。
ls | wc -l
ls -l | grep -e -x -e -dr | wc -l
长列表过滤文件和目录计数过滤的行号
不定期副业成功案例分享
-type f
以将目录包括在计数中-print0
标志。wc
的某些实现具有读取空终止列表的选项。请参阅我的答案以获取替代方案。find . -type f -exec echo \; | wc -l
。这样,您实际上并没有输出文件名,而是输出每个遇到的文件一个空行,而不管名称如何,因此行数在任何情况下都有效。如果您只计算空字符,print0 也可以工作:find . -type f -print0 | tr -dc '\0' | wc -c
。在这种情况下, tr 删除所有非空字符并 wc 计算输入它的字符。