我需要一个计算目录(和子目录)中文件数量的脚本。我采用了以下脚本,并将其更改为我的需要。
除了带有空格字符的文件夹之外,它的工作方式与应有的方式相同。我很确定我在任何地方都缺少引号,但还无法弄清楚。
附加信息
- Linux 2.6.22.19-0.4-default(该服务器不再处于生产环境中。)
- GNU 查找版本 4.2.31
- 我无法重命名目录。
目录结构示例
.
..
01_infos
02_sent
03_inbox
04_public and private
197.
145.
329.
13.
脚本
#!/bin/bash
# Write a script that will count the number of files in each of your subdirectories.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
START=$HOME
# change your directory to command line if passed
# otherwise use home directory
[ $# -eq 1 ] && START=$1 || :
if [ ! -d $START ]
then
echo "$START not a directory!"
exit 1
fi
# use find command to get all subdirs name in DIRS variable
DIRS=$(find "$START" -type d)
# loop thought each dir to get the number of files in each of subdir
for d in $DIRS
do
echo "$d directory has $(find "$d" -maxdepth 1 -regex '.*\.' -type f | wc -l) files" || :
done
输出
./01_infos directory has 1 files
./02_sent directory has 9 files
./03_inbox has 4 files
find: ./04_public: No such file or directory
答案1
你缺少一些双引号(总是在变量替换两边加上双引号$foo
始终在变量替换和命令替换$(foo)
,除非您知道为什么可以安全地离开它们并且需要离开它们)。但这还不是问题的全部。
if [ ! -d $START ]
应该if [ ! -d "$START" ]
。
DIRS=$(find "$START" -type d)
此时,DIRS
递归包含起始目录及其子目录的名称,中间有换行符。因此,如果您有任何包含换行符的目录名称,您就迷失了:不可能知道哪些换行符来自目录名以及哪些是分隔符。如果您知道文件名中没有换行符,则可以解析 的输出find
,但您怎么知道呢?
顺便说一句,这里没有双引号是可以的,$(…)
因为这是一个变量赋值,并且赋值中的替换是隐式保护的。但请注意,它没有受到类似的保护。最好使用引号,除非您精通 shell 脚本编写,并且所有维护您的脚本的人也是如此。export DIRS=$(…)
for d in $DIRS
这就是你失败的地方:你想分成$DIRS
单词,所以你不能加双引号,但你需要双引号,因为$DIRS
所有元素都连接在一起,并且如果你不加引号,空格内的文件名将成为分隔符。
通常,当您使用 时find
,您应该让它调用处理命令,并带有-exec
选项。除非您对文件名有严格的控制,否则不要解析 的输出find
:它是不明确的。
find "$START" -type d -exec sh -c '
echo "$0 directory has $(find "$0" -maxdepth 1 -regex ".*\\." -type f -printf \\n | wc -l) files whose name ends with ."
' {} \;
再次注意,在嵌入find
命令中,如果解析 的输出find
,如果任何文件名包含换行符,则计数将被关闭。
答案2
就这个怎么样?
find . -type d -exec sh -c '/bin/echo -n "{}"; find "{}" -maxdepth 1 -regex ".*\." -type f | wc -l; ' \;
输出并不那么甜蜜,但它不需要脚本,并且适用于带有空格以及其他非字母数字字符的目录。
答案3
你有一个经典的引用错误。将 for 循环修复为如下所示:
for d in "$DIRS"
或者,您可以find
直接输入它的输出,例如:
find "$START" -type d | while read d
do # and so on...
顺便说一句,该|| :
位是完全多余的,因为echo
返回值始终为 0。