Linux 查找目录中的文件数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3702104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find the number of files in a directory
提问by yassin
Is there any method in Linux to calculate the number of files in a directory (that is, immediate children) in O(1) (independently of the number of files) without having to list the directory first? If not O(1), is there a reasonably efficient way?
Linux中是否有任何方法可以在O(1)(与文件数无关)中计算目录中的文件数(即直接子项)而不必先列出目录?如果不是 O(1),是否有合理有效的方法?
I'm searching for an alternative to ls | wc -l
.
我正在寻找替代ls | wc -l
.
采纳答案by Phil
readdir is not as expensive as you may think. The knack is avoid stat'ing each file, and (optionally) sorting the output of ls.
readdir 并不像您想象的那么昂贵。诀窍是避免统计每个文件,并(可选)对 ls 的输出进行排序。
/bin/ls -1U | wc -l
/bin/ls -1U | wc -l
avoids aliases in your shell, doesn't sort the output, and lists 1 file-per-line (not strictly necessary when piping the output into wc).
避免在您的 shell 中使用别名,不对输出进行排序,并每行列出 1 个文件(在将输出管道传输到 wc 时不是绝对必要的)。
The original question can be rephrased as "does the data structure of a directory store a count of the number of entries?", to which the answer is no. There isn't a more efficient way of counting files than readdir(2)/getdents(2).
最初的问题可以改写为“目录的数据结构是否存储条目数的计数?”,答案是否定的。没有比 readdir(2)/getdents(2) 更有效的文件计数方法了。
回答by taskinoor
As far as I know, there is no better alternative. This information might be off-topic to this question and you may already know this that under Linux (in general under Unix) directories are just special file which contains the list of other files (I understand that the exact details will be dependent on specific file system but this is the general idea). And there is no call to find the total number of entries without traversing the whole list. Please make me correct if I'm wrong.
据我所知,没有更好的选择。此信息可能与此问题无关,您可能已经知道在 Linux 下(通常在 Unix 下)目录只是包含其他文件列表的特殊文件(我知道确切的细节将取决于特定文件系统,但这是总体思路)。并且无需遍历整个列表即可查找条目总数。如果我错了,请纠正我。
回答by pj_
One can get the number of subdirectories of a given directory without traversing the whole list by stat'ing (stat(1) or stat(2)) the given directory and observing the number of links to that directory. A given directory with N child directories will have a link count of N+2, one link for the ".." entry of each subdirectory, plus two for the "." and ".." entries of the given directory.
可以通过统计(stat(1) 或 stat(2))给定目录并观察到该目录的链接数来获取给定目录的子目录数,而无需遍历整个列表。具有 N 个子目录的给定目录的链接数为 N+2,每个子目录的“..”条目有一个链接,“.”条目加上两个链接。和给定目录的“..”条目。
However one cannot get the number of all files (whether regular files or subdirectories) without traversing the whole list -- that is correct.
但是,如果不遍历整个列表,就无法获得所有文件(无论是常规文件还是子目录)的数量——这是正确的。
The "/bin/ls -1U" command will not get all entries however. It will get onlythose directory entries that do not start with the dot (.) character. For example, it would not count the ".profile" file found in many login $HOME directories.
但是,“/bin/ls -1U”命令不会获取所有条目。它会得到唯一不以点(。)字符开头的目录条目。例如,它不会计算在许多登录 $HOME 目录中找到的“.profile”文件。
One can use either the "/bin/ls -f" command or the "/bin/ls -Ua" command to avoid the sort and get all entries.
可以使用“/bin/ls -f”命令或“/bin/ls -Ua”命令来避免排序并获取所有条目。
Perhaps unfortunately for your purposes, either the "/bin/ls -f" command or the "/bin/ls -Ua" command will also count the "." and ".." entries that are in each directory. You will have to subtract 2 from the count to avoid counting these two entries, such as in the following:
也许不幸的是,“/bin/ls -f”命令或“/bin/ls -Ua”命令也将计算“。” 和每个目录中的“..”条目。您必须从计数中减去 2 以避免计算这两个条目,例如:
expr `/bin/ls -f | wc -l` - 2 # Those are back ticks, not single quotes.
The --format=single-column (-1) option is not necessary on the "/bin/ls -Ua" command when piping the "ls" output, as in to "wc" in this case. The "ls" command will automatically write its output in a single column if the output is not a terminal.
在通过管道传输“ls”输出时,“/bin/ls -Ua”命令中不需要 --format=single-column (-1) 选项,在本例中为“wc”。如果输出不是终端,“ls”命令将自动将其输出写入单列。
回答by Venkataramesh Kommoju
use ls -1 | wc -l
使用 ls -1 | wc -l
回答by user2991011
I used this command..works like a charm..only to change the maxdepth..that is sub directories
我用了这个命令..像魅力一样工作..只改变最大深度..那是子目录
find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;
回答by nisetama
The -U
option for ls
is not in POSIX, and in OS X's ls
it has a different meaning from GNU ls
, which is that it makes -t
and -l
use creation times instead of modification times. -f
is in POSIX as an XSI extension. The manual of GNU ls
describes -f
as do not sort, enable -aU, disable -ls --color
and -U
as do not sort; list entries in directory order
.
在-U
对选项ls
是不是在POSIX,而在OS X的ls
它已经从GNU不同的意义ls
,这是它使得-t
与-l
使用创建时间,而不是修改时间。-f
在 POSIX 中作为 XSI 扩展。GNU的手动ls
描述-f
为do not sort, enable -aU, disable -ls --color
和-U
为do not sort; list entries in directory order
。
POSIX describes -f
like this:
POSIX 是-f
这样描述的:
Force each argument to be interpreted as a directory and list the name found in each slot. This option shall turn off
-l
,-t
,-s
, and-r
, and shall turn on-a
; the order is the order in which entries appear in the directory.
强制将每个参数解释为一个目录并列出在每个插槽中找到的名称。此选项应关闭
-l
、-t
、-s
和-r
,并应打开-a
;order 是条目在目录中出现的顺序。
Commands like ls|wc -l
give the wrong result when filenames contain newlines.
ls|wc -l
当文件名包含换行符时,命令会给出错误的结果。
In zsh you can do something like this:
在 zsh 中,您可以执行以下操作:
a=(*(DN));echo ${#a}
D
(glob_dots
) includes files whose name starts with a period and N
(null_glob
) causes the command to not result in an error in an empty directory.
D
( glob_dots
) 包括名称以句点开头的文件,并且N
( null_glob
) 导致命令不会在空目录中导致错误。
Or the same in bash:
或者在 bash 中相同:
shopt -s dotglob nullglob;a=(*);echo ${#a[@]}
If IFS
contains ASCII digits, add double quotes around ${#a[@]}
. Add shopt -u failglob
to ensure that failglob
is unset.
如果IFS
包含 ASCII 数字,请在${#a[@]}
. 添加shopt -u failglob
以确保failglob
未设置。
A portable option is to use find
:
一个便携式选项是使用find
:
find . ! -name . -prune|grep -c /
grep -c /
can be replaced with wc -l
if filenames do not contain newlines. ! -name . -prune
is a portable alternative to -mindepth 1 -maxdepth 1
.
grep -c /
wc -l
如果文件名不包含换行符,则可以替换为。! -name . -prune
是-mindepth 1 -maxdepth 1
.
Or here's another alternative that does not usually include files whose name starts with a period:
或者这是另一种通常不包含名称以句点开头的文件的替代方法:
set -- *;[ -e "" ]&&echo "$#"
The command above does however include files whose name starts with a period when an option like dotglob
in bash or glob_dots
in zsh is set. When *
matches no file, the command results in an error in zsh with the default settings.
但是,上面的命令确实包含名称以句点开头的文件,当设置了dotglob
bash 或glob_dots
zsh等选项时。当*
没有匹配文件时,该命令会在 zsh 中使用默认设置导致错误。
回答by fedorqui 'SO stop harming'
I think you can have more control on this using find
:
我认为您可以使用find
以下方法对此进行更多控制:
find <path> -maxdepth 1 -type f -printf "." | wc -c
find -maxdepth 1
will not go deeper into the hierarchy of files.-type f
allows filtering to just files. Similarly, you can use-type d
for directories.-printf "."
prints a dot for every match.wc -c
counts the characters, so it counts the dots created by theprint
... which means counting how many files exist in the given path.
find -maxdepth 1
不会深入到文件的层次结构中。-type f
允许只过滤文件。同样,您可以-type d
用于目录。-printf "."
为每场比赛打印一个点。wc -c
计算字符数,因此它计算print
...创建的点数,这意味着计算给定路径中存在的文件数量。
回答by chry
For the number of all file in a current directory try this:
对于当前目录中所有文件的数量,试试这个:
ls -lR * | wc -l