脚本错误。命令 find 正在跳过带有空格字符的文件夹

脚本错误。命令 find 正在跳过带有空格字符的文件夹

我需要一个计算目录(和子目录)中文件数量的脚本。我采用了以下脚本,并将其更改为我的需要。

除了带有空格字符的文件夹之外,它的工作方式与应有的方式相同。我很确定我在任何地方都缺少引号,但还无法弄清楚。

附加信息

  • 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,但您怎么知道呢?

顺便说一句,这里没有双引号是可以的,$(…)因为这是一个变量赋值,并且赋值中的替换是隐式保护的。但请注意,它export DIRS=$(…)没有受到类似的保护。最好使用引号,除非您精通 shell 脚本编写,并且所有维护您的脚本的人也是如此。

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。

相关内容