我需要检查所有子目录并报告它们包含多少个文件(无需进一步递归):
directoryName1 numberOfFiles
directoryName2 numberOfFiles
答案1
这是以一种安全且便携的方式完成的。它不会被奇怪的文件名混淆。
for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \; | wc -l && echo $f; done
请注意,它将首先打印文件数,然后在单独的行上打印目录名称。如果您想保留OP的格式,您将需要进一步格式化,例如
for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \;|wc -l|tr '\n' ' ' && echo $f; done|awk '{print $2"\t"$1}'
如果您有一组感兴趣的特定子目录,则可以*
用它们替换 。
为什么这样安全?(因此值得剧本)
文件名可以包含除/
.有一些字符由 shell 或命令进行特殊处理。其中包括空格、换行符和破折号。
使用该for f in *
构造是获取每个文件名的安全方法,无论它包含什么。
一旦将文件名放入变量中,您仍然必须避免诸如find $f
.如果$f
包含 filename -test
,find
则会抱怨您刚刚提供的选项。避免这种情况的方法是./
在名称前面使用;这样它具有相同的含义,但不再以破折号开头。
换行符和空格也是一个问题。如果$f
包含“hello, buddy”作为文件名,则find ./$f
, 是find ./hello, buddy
.你告诉我们find
要看看./hello,
和buddy
。如果那些不存在,它会抱怨,并且永远不会查找./hello, buddy
。这很容易避免 - 在变量周围使用引号。
最后,文件名可以包含换行符,因此在文件名列表中计算换行符将不起作用;对于带有换行符的每个文件名,您都会获得额外的计数。为了避免这种情况,不要计算文件列表中的换行符;相反,计算代表单个文件的换行符(或任何其他字符)。这就是为什么该find
命令有 simple-exec echo \;
和 not 的原因-exec echo {} \;
。我只想打印一个新行来统计文件。
答案2
“无递归”是指如果directoryName1
有子目录,那么您不想计算子目录中的文件吗?如果是这样,这里有一种方法来计算指定目录中的所有常规文件:
count=0
for d in directoryName1 directoryName2; do
for f in "$d"/* "$d"/.[!.]* "$d"/..?*; do
if [ -f "$f" ]; then count=$((count+1)); fi
done
done
请注意,该-f
测试执行两个功能:它测试上面的 glob 之一匹配的条目是否是常规文件,并测试该条目是否匹配(如果其中一个 glob 不匹配任何内容,则模式保持原样 1)。如果要计算给定目录中的所有条目(无论其类型如何),请替换-f
为-e
.
Ksh 有一种方法可以使模式与点文件匹配,并在没有文件与模式匹配的情况下生成一个空列表。因此,在 ksh 中,您可以像这样计算常规文件:
FIGNORE='.?(.)'
count=0
for x in ~(N)directoryName1/* ~(N)directoryName2/*; do
if [ -f "$x" ]; then ((++count)); fi
done
或所有文件都像这样:
FIGNORE='.?(.)'
files=(~(N)directoryName1/* ~(N)directoryName2/*)
count=${#files}
Bash 有不同的方法来简化这个过程。要计算常规文件:
shopt -s dotglob nullglob
count=0
for x in directoryName1/* directoryName2/*; do
if [ -f "$x" ]; then ((++count)); fi
done
计算所有文件的数量:
shopt -s dotglob nullglob
files=(directoryName1/* directoryName2/*)
count=${#files}
和往常一样,在 zsh 中甚至更简单。要计算常规文件:
files=({directoryName1,directoryName2}/*(DN.))
count=$#files
更改(DN.)
为(DN)
对所有文件进行计数。
1请注意,每个模式都与自身匹配,否则结果可能会出错(例如,如果您正在计算以数字开头的文件,则不能只是这样做,for x in [0-9]*; do if [ -f "$x" ]; then …
因为可能有一个名为 的文件[0-9]foo
)。
答案3
假设您正在寻找标准的 Linux 解决方案,实现此目标的一个相对简单的方法是find
:
find dir1/ dir2/ -maxdepth 1 -type f | wc -l
wherefind
遍历两个指定的子目录,a 为-maxdepth
1,这样可以防止进一步递归,并且仅报告-type f
由换行符分隔的文件 ( )。然后将结果通过管道传送到wc
计算这些行的数量。
答案4
这是一种获得结果的“蛮力”方式,使用find
、echo
、ls
、wc
和。xargs
awk
find . -maxdepth 1 -type d -exec sh -c "echo '{}'; ls -1 '{}' | wc -l" \; | xargs -n 2 | awk '{print $1" "$2}'