如何使用 bash 脚本列出(并查找文件数)目录?
How can I list (and find the number of files) of directories with a bash script?
我有一个目录和子目录的结构,它们在终点包含一些扩展名的文件(比如 jpg 文件)
目录结构未设置。所以它可以像
top_directory
|__child1
| |__one
| |_two
|
|__child2
| |_three
|
|__child3
|_child3_1
|__four
|__five
|__six
如何制作一个脚本来计算存在的子目录中所述扩展的文件数。
以前只有一级子目录的时候我是这样做的
for entry in ./*/
do
echo "$entry"
ls "$entry"/*.jpg -l | wc -l
done
这对 entry
遍历了所有子目录并对文件进行了计数。
然而,当有 sub sud 目录时,这显然不起作用。
使用 GNU 查找 -printf
。
find /top/dir -type f -name '*.jpg' -printf . | wc -c
与 ls
(通常不应在脚本中使用)不同,即使文件名包含换行符,它也能正常工作。
编辑:每个 sub-directory 的文件计数(在评论中询问):
有几种方法可以做到这一点,但也许像这样。它适用于交互式输出(即显示给用户)。您将看到每个子目录及其计数。除非,包含零个 .jpg
个文件的目录将不会被列出(无论是赞成还是反对,取决于用例)。
find /top/dir -type f -name '*.jpg' -exec dirname -z -- {} + |
sort -z |
uniq -zc |
sort -znk 1,1 |
tr '[=11=]' '\n'
这需要 GNU 工具来处理空定界符(-z
标志)。第二个排序排序计数,从低到高。添加 -r
(反向)从高到低。
这里有一个不是特别聪明的方法(它有效地完成了你正在做的事情,但递归地并且没有解决文件名并不意味着它们是 JPG 的问题)-
( find . -type d -print | while read line; do echo "$line" $( ls -1 "$line"/*.jpg 2>/dev/null | wc -l); done ) | grep -v ' 0$'
与您的请求非常相似的内容已在 unix & linux SO
得到详细答复
@dan 有一个很好的方法,但是使用 helper-script 来计算找到的每个目录中的文件的类似方法是另一种简单且相当有效的方法。使用 find
命令,您将递归地找到给定目录下的子目录。您检索目录名称:
find /top/dir -type d -print -exec ./helperf '{}' jpg \;
上面的 -print
是可选的,它只是在帮助脚本 (helperf
) 输出该目录中的文件数之前输出当前目录名称。 jpg
(或任何文件扩展名)同样是可选的,如果省略,则计算给定目录中的所有文件。由于您使用 -exec
调用您的帮助脚本,因此您应该使它可执行(或包括完整的 bash 调用)
辅助函数 helperf
简单地调用 find
类似于 @dan 的提议,但将 -maxdepth
限制为 1
因此只计算该目录中的文件.您的帮助脚本可以是:
#!/bin/bash
[ -d "" ] && { ## first param is directory
if [ -n "" ]; then ## ext given as second param
find "" -maxdepth 1 -type f -name "*." -printf . 2>/dev/null | wc -c
else ## no ext given, count all files
find "" -maxdepth 1 -type f -printf . 2>/dev/null | wc -c
fi
}
以上:
[ -d "" ]
用作简单验证,确保传递的参数是有效目录。如果没有,脚本会自动退出。
if [ -n "" ]; then
检查是否给出了第二个扩展名参数,如果是,文件上的 find
仅限于以该扩展名结尾的文件。没有它,目录中的所有文件都被计算在内。
示例Use/Output
鉴于我在这个盒子上的 tmp
目录具有以下结构:
tree -d
.
├── awk
├── clamav
│ └── src
└── st
检查所有文件导致:
$ find . -type d -print -exec ./helperf '{}' \;
.
40
./clamav
5
./clamav/src
0
./awk
2
./st
3
目录中的文件总数是正确的。
现在仅限 .txt
个文件(父目录中只有 6 个文件),您将拥有:
$ find . -type d -print -exec ./helperf '{}' txt \;
.
6
./clamav
0
./clamav/src
0
./awk
0
./st
0
这似乎与您要查找的内容接近。查看它,如果您还有其他问题,请告诉我。
我有一个目录和子目录的结构,它们在终点包含一些扩展名的文件(比如 jpg 文件) 目录结构未设置。所以它可以像
top_directory
|__child1
| |__one
| |_two
|
|__child2
| |_three
|
|__child3
|_child3_1
|__four
|__five
|__six
如何制作一个脚本来计算存在的子目录中所述扩展的文件数。
以前只有一级子目录的时候我是这样做的
for entry in ./*/
do
echo "$entry"
ls "$entry"/*.jpg -l | wc -l
done
这对 entry
遍历了所有子目录并对文件进行了计数。
然而,当有 sub sud 目录时,这显然不起作用。
使用 GNU 查找 -printf
。
find /top/dir -type f -name '*.jpg' -printf . | wc -c
与 ls
(通常不应在脚本中使用)不同,即使文件名包含换行符,它也能正常工作。
编辑:每个 sub-directory 的文件计数(在评论中询问):
有几种方法可以做到这一点,但也许像这样。它适用于交互式输出(即显示给用户)。您将看到每个子目录及其计数。除非,包含零个 .jpg
个文件的目录将不会被列出(无论是赞成还是反对,取决于用例)。
find /top/dir -type f -name '*.jpg' -exec dirname -z -- {} + |
sort -z |
uniq -zc |
sort -znk 1,1 |
tr '[=11=]' '\n'
这需要 GNU 工具来处理空定界符(-z
标志)。第二个排序排序计数,从低到高。添加 -r
(反向)从高到低。
这里有一个不是特别聪明的方法(它有效地完成了你正在做的事情,但递归地并且没有解决文件名并不意味着它们是 JPG 的问题)-
( find . -type d -print | while read line; do echo "$line" $( ls -1 "$line"/*.jpg 2>/dev/null | wc -l); done ) | grep -v ' 0$'
与您的请求非常相似的内容已在 unix & linux SO
得到详细答复@dan 有一个很好的方法,但是使用 helper-script 来计算找到的每个目录中的文件的类似方法是另一种简单且相当有效的方法。使用 find
命令,您将递归地找到给定目录下的子目录。您检索目录名称:
find /top/dir -type d -print -exec ./helperf '{}' jpg \;
上面的 -print
是可选的,它只是在帮助脚本 (helperf
) 输出该目录中的文件数之前输出当前目录名称。 jpg
(或任何文件扩展名)同样是可选的,如果省略,则计算给定目录中的所有文件。由于您使用 -exec
调用您的帮助脚本,因此您应该使它可执行(或包括完整的 bash 调用)
辅助函数 helperf
简单地调用 find
类似于 @dan 的提议,但将 -maxdepth
限制为 1
因此只计算该目录中的文件.您的帮助脚本可以是:
#!/bin/bash
[ -d "" ] && { ## first param is directory
if [ -n "" ]; then ## ext given as second param
find "" -maxdepth 1 -type f -name "*." -printf . 2>/dev/null | wc -c
else ## no ext given, count all files
find "" -maxdepth 1 -type f -printf . 2>/dev/null | wc -c
fi
}
以上:
[ -d "" ]
用作简单验证,确保传递的参数是有效目录。如果没有,脚本会自动退出。if [ -n "" ]; then
检查是否给出了第二个扩展名参数,如果是,文件上的find
仅限于以该扩展名结尾的文件。没有它,目录中的所有文件都被计算在内。
示例Use/Output
鉴于我在这个盒子上的 tmp
目录具有以下结构:
tree -d
.
├── awk
├── clamav
│ └── src
└── st
检查所有文件导致:
$ find . -type d -print -exec ./helperf '{}' \;
.
40
./clamav
5
./clamav/src
0
./awk
2
./st
3
目录中的文件总数是正确的。
现在仅限 .txt
个文件(父目录中只有 6 个文件),您将拥有:
$ find . -type d -print -exec ./helperf '{}' txt \;
.
6
./clamav
0
./clamav/src
0
./awk
0
./st
0
这似乎与您要查找的内容接近。查看它,如果您还有其他问题,请告诉我。