Zan*_*nna 29 command-line files ls
显然我数不过来。我认为有三个文件/media
$ tree /media
/media
??? foo
??? onex
??? zanna
3 directories, 0 files
Run Code Online (Sandbox Code Playgroud)
然而,ls -l
发现 12。
$ ls -l /media
total 12
drwxr-xr-x 2 root root 4096 Jul 31 20:57 foo
drwxrwxr-x 2 root root 4096 Jun 26 06:36 onex
drwxr-x---+ 2 root root 4096 Aug 7 21:17 zanna
Run Code Online (Sandbox Code Playgroud)
而且,如果我这样做,ls -la
我只会得到.
并且..
除了上述之外,但计数是total 20
解释是什么?
use*_*274 38
在12
你看到的是不是文件的数量,但磁盘块的数量消耗。
来自info coreutils 'ls invocation'
:
For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory. The block size currently defaults to 1024
bytes, but this can be overridden (*note Block size::). The
BLOCKS computed counts each hard link separately; this is arguably
a deficiency.
Run Code Online (Sandbox Code Playgroud)
当您使用而不是因为您正在计算两个额外的目录时,总数从12
到:和。您为每个(空)目录使用四个磁盘块,因此您的总数从 3 × 4 变为 5 × 4。(很可能,您为每个目录使用了一个4096 字节的磁盘块;如页面所示,实用程序不检查磁盘格式,但除非另有说明,否则假定块大小为。)20
ls -la
ls -l
.
..
info
1024
如果您只想获取文件数,您可以尝试类似
ls | wc -l
Run Code Online (Sandbox Code Playgroud)
Ser*_*nyy 18
user4556274 已经回答了原因。我的回答仅用于提供有关如何正确计算文件的附加信息。
在 Unix 社区中,普遍的共识是解析 的输出ls
是一个非常非常糟糕的主意,因为文件名可以包含控制字符或隐藏字符。例如,由于文件名中的换行符,我们ls | wc -l
告诉我们ls
(它确实有)的输出中有 5 行,但实际上目录中只有 4 个文件。
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Run Code Online (Sandbox Code Playgroud)
The find
command, which is typically used for working around parsing filenames, can help us here by printing the inode number. Be it a directory or a file, it only has one unique inode number. Thus, using -printf "%i\n"
and excluding .
via -not -name "."
we can have an accurate count of the files. (Note the use of -maxdepth 1
to prevent recursive descending into subdirectories)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
Run Code Online (Sandbox Code Playgroud)
Simple, quick, and mostly portable way:
$ set -- *
$ echo $#
228
Run Code Online (Sandbox Code Playgroud)
set
command is used to set positional parameters of the shell ( the $<INTEGER>
variables, as in echo $1
). This is often used to work around /bin/sh
limitation of lacking arrays. A version that performs extra checks can be found in Gille's answer over on Unix&Linux.
In shells that support arrays, such as bash
, we can use
items=( dir/* )
echo ${#items[@]}
Run Code Online (Sandbox Code Playgroud)
as proposed by steeldriver in the comments.
Similar trick to find
method which used wc
and globstar can be used with stat
to count inode numbers per line:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Run Code Online (Sandbox Code Playgroud)
An alternative approach is to use a wildcard in for
loop. (Note, this test uses a different directory to test whether this approach descends into subdirectories, which it does not - 16 is the verified number of items in my ~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Run Code Online (Sandbox Code Playgroud)
Python can also deal with problematic filenames via printing the length of a list given my os.listdir()
function (which is non-recursive, and will only list items in the directory given as argument).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
Run Code Online (Sandbox Code Playgroud)