如何递归计算Linux目录中的文件?
我找到了这个:
find DIR_NAME -type f ¦ wc -l
但是,当我运行它时,它返回以下错误。
find:路径必须在表达式之前:¦
*
“星号” ASCII字符一样,但是在其他一些上下文中则是“时间”。
如何递归计算Linux目录中的文件?
我找到了这个:
find DIR_NAME -type f ¦ wc -l
但是,当我运行它时,它返回以下错误。
find:路径必须在表达式之前:¦
*
“星号” ASCII字符一样,但是在其他一些上下文中则是“时间”。
Answers:
这应该工作:
find DIR_NAME -type f | wc -l
说明:
-type f
仅包含文件。|
(而不是¦
)将find
命令的标准输出重定向到wc
命令的标准输入。wc
(字数计数的缩写)在其输入(docs)上计算换行符,单词和字节。-l
仅计算换行符。笔记:
DIR_NAME
为.
在当前文件夹要执行的命令。-type f
以在计数中包含目录(和符号链接)。您的示例为何无效的说明:
在显示的命令中,您并没有使用“管道”(|
)来连接两个命令,而是用断线(¦
)将外壳识别为命令或类似内容。这就是为什么您收到该错误消息的原因。
f
在-type f
代表文件和wc -l
词数线。
-type f
要包括目录在内的目录
-print
标志
-print0
标志。
wc
具有读取空终止列表的选项。请参阅我的答案。
如果要细分当前目录下每个目录中有多少个文件,请执行以下操作:
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
解决。请参阅如何逐行(和/或逐字段)读取文件(数据流,变量)?
find
的外环只是一个不必要的并发症。for i in */
; 做`
您可以使用
$ tree
在安装树包之后
$ sudo apt-get install tree
(在Debian / Mint / Ubuntu Linux机器上)。
该命令不仅分别显示文件数,而且还显示目录数。选项-L可用于指定最大显示级别(默认情况下,该级别是目录树的最大深度)。
通过提供-a
选项,也可以包含隐藏文件。
-a
包括它们的选项。
brew
并运行brew install tree
,最好先运行brew update
。
在我的计算机上,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
第二行具有文件数,在上面的示例中为150481。作为奖励,您还可以获得总大小(以字节为单位)。
备注:
--dry-run
(或-n
简称)选项没有实际传输文件是很重要的!-x
“不越过文件系统边界” 的选项,这意味着如果执行该选项/
并且连接了外部硬盘,它将仅计算根分区上的文件。find ~ -type f | wc -l
花费了1.7 / 0.5 / 1.33秒(真实/用户/ sys)。rsync --stats --dry-run -ax ~ /xxx
花了4.4 / 3.1 / 2.1秒。固态硬盘上大约有500,000个文件。
Number of files: 487 (reg: 295, dir: 192)
rsync version 2.6.9 protocol version 29
由于UNIX中的文件名可能包含换行符(是,换行符),因此wc -l
文件数可能过多。我会为每个文件打印一个点,然后计算点数:
find DIR_NAME -type f -printf "." | wc -c
结合这里的几个答案,最有用的解决方案似乎是:
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`)将一个问题换成另一个问题。
如果要避免出现错误情况,请不要允许 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
您可以使用命令ncdu
。它将递归计算Linux目录包含多少个文件。这是输出示例:
它有一个进度条,如果您有许多文件,这将很方便:
要在Ubuntu上安装它:
sudo apt-get install -y ncdu
基准测试:我使用了https://archive.org/details/cv_corpus_v1.tar个文件,11 GB)作为必须计算文件数量的文件夹。
find . -type f | wc -l
:大约1m20s完成ncdu
:大约1m20s完成find . -type f | wc -l
和之间的任何区别ncdu
。
find
大致相同的系统调用。只是把他们拉了一下。du
ncdu
tree $DIR_PATH | tail -1
样本输出:
5309目录,2122文件
要确定当前目录中有多少个文件,请输入ls -1 | wc -l
。这用于wc
对(-l)
的输出中的行数进行计数ls -1
。它不计算点文件。请注意ls -l
我在本HOWTO的早期版本中使用的(这是一个“ L”,而不是前面的示例中的“ 1”)实际上将使您的文件计数比实际计数大一。感谢Kam Nejad的观点。
如果您只想计算文件并且不包括符号链接(仅是您可以做的事情的一个例子),则可以使用ls -l | grep -v ^l | wc -l
(这次是“ L”而不是“ 1”,我们希望在此处列出“ long”) 。grep
检查以“ l”开头(指示链接)的任何行,并丢弃该行(-v)。
相对速度:在卸载的486SX25上,“ ls -1 / usr / bin / | wc -l”大约需要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
。
用bash:
使用()创建一个条目数组,并使用#获取计数。
FILES=(./*); echo ${#FILES[@]}
好的,这不会递归计数文件,但我想先显示简单的选项。常见的用例可能是创建文件的过渡备份。这将创建logfile.1,logfile.2,logfile.3等。
CNT=(./logfile*); mv logfile logfile.${#CNT[@]}
globstar
启用bash 4+的递归计数(如@tripleee所述)
FILES=(**/*); echo ${#FILES[@]}
为了递归地获取文件数,我们仍然可以以相同的方式使用find。
FILES=(`find . -type f`); echo ${#FILES[@]}
**/*
递归枚举。它仍然不如find
大型目录有效,因为外壳程序必须对每个目录中的文件进行排序。
对于名称中带有空格的目录...(基于上述各种答案)-递归打印目录名称,其中包含以下文件数量:
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 /
(以下使用)来自/unix/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
这将完全正常。简单简短。如果要计算文件夹中存在的文件数。
ls | wc -l
¦
(ASCII 166)与|
用于UNIX管道的竖线(ASCII 124)混淆。