问题描述
显然我无法计数。我认为/media
中有三个文件
$ tree /media
/media
├── foo
├── onex
└── zanna
3 directories, 0 files
但是,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
而且,如果我执行ls -la
,除了上述内容之外,我还将仅获得.
和..
,但计数为total 20
有什么解释?
最佳方法
您看到的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.
当您使用ls -la
而不是ls -l
时,总数从12
到20
,因为您要计算的是另外两个目录:.
和..
。您为每个(空)目录使用四个磁盘块,因此总数从3×4变为5×4。(很可能,您为每个目录使用一个4096字节的磁盘块;正如info
页所指示的,除非另有说明,否则该实用程序不会检查磁盘格式,但会假定其块大小为1024
。)
如果您只想获取文件数,则可以尝试类似
ls | wc -l
次佳方法
user4556274 has already answered为什么。我的回答仅用于提供有关如何正确计数文件的其他信息。
在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
方法1:查找实用程序
find
命令通常用于解析文件名,它可以通过打印inode number来帮助我们。无论是目录还是文件,它都只有一个唯一的索引节点号。因此,使用-printf "%i\n"
并通过-not -name "."
排除.
,我们可以对文件进行准确计数。 (请注意,使用-maxdepth 1
可以防止递归下降到子目录中)
$> 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
方法#2:globstar
简单,快速且通常可移植的方式:
$ set -- *
$ echo $#
228
set
命令用于设置 shell 的位置参数(如echo $1
中的$<INTEGER>
变量)。这通常用于解决/bin/sh
缺少数组的限制。可以在Unix&Linux上的Gille’s answer中找到执行额外检查的版本。
在支持数组的shell中,例如bash
,我们可以使用
items=( dir/* )
echo ${#items[@]}
由steeldriver in the comments提出。
与使用wc
和globstar的find
方法类似的技巧可以与stat
一起使用以计算每行的索引节点数:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
一种替代方法是在for
循环中使用通配符。 (请注意,此测试使用不同的目录来测试此方法是否归入子目录,而不是子目录-16是我的~/bin
中已验证的项目数)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
方法3:其他语言/口译员
Python还可以通过打印给定我的os.listdir()
函数的列表长度来处理有问题的文件名(这是非递归的,并且只会列出作为参数给出的目录中的项)。
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4