显然我数不过来。我认为有三个文件/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
怎么解释?
答案1
你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.
当您使用而不是时,总数将从 变为12
,因为您要计算两个附加目录:和。您为每个(空)目录使用 4 个磁盘块,因此总数将从 3 × 4 变为 5 × 4。(最有可能的是,您正在使用20
ls -la
ls -l
.
..
一每个目录的磁盘块为 4096 字节;如页面info
所示,该实用程序不检查磁盘格式,但假定块大小为,1024
除非另有说明。)
如果你只想获取文件数量,你可以尝试类似
ls | wc -l
答案2
user4556274 已经回答这为什么。我的回答仅用于提供补充信息如何正确计数文件。
在 Unix 社区中,普遍的共识是解析输出ls
是一个非常糟糕的主意,因为文件名可以包含控制字符或隐藏字符。例如,由于文件名中有换行符,我们被ls | wc -l
告知输出中有 5 行ls
(确实有),但实际上目录中只有 4 个文件。
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
方法一:寻找效用
该find
命令通常用于解决文件名解析问题,它可以帮助我们打印索引节点号。无论是目录还是文件,它都只有一个唯一的 inode 编号。因此,使用-printf "%i\n"
并排除.
via-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 的位置参数($<INTEGER>
变量,如echo $1
)。这通常用于解决/bin/sh
缺少数组的限制。执行额外检查的版本可以在Gille 的回答在Unix和Linux上。
在支持数组的 shell 中,例如bash
,我们可以使用
items=( dir/* )
echo ${#items[@]}
按照提议steeldriver 在评论中。
find
与使用的方法类似的技巧wc
,可以使用 globstar 来stat
计算每行的 inode 数量:
$> 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