递归打印文件夹中的文件数

时间:2013-12-10 10:13:34

标签: bash

我挣扎了几个小时才能让这条uggly系列工作

wcr() { find "$@" -type d | while read F; do find $F -maxdepth 0 && printf "%5d " $(ls $F | wc) && printf "$F"; done; echo; }

结果如下

39   41  754 ../matlab.sh
1    1   19 ./matlab.sh./micmac
1    1   14 ./micmac

我的第一个问题是:我怎样才能更聪明地写出来?

第二个问题:我希望在计数之前打印名称,但我不知道如何将输出列表,所以我不能做得比这更好:

.
./matlab.sh   1    1   19 
./matlab.sh./micmac    1    1   19
./micmac   1    1   14 

2 个答案:

答案 0 :(得分:3)

  1. 我看不出那find $F -maxdepth 0会有什么好处,所以我只是剥掉它。
  2. 此外,如果文件名包含%,如果您将其用作printf的格式字符串,则会遇到麻烦,因此我会添加一个显式格式字符串。我合并了两个printf。要切换列(有关此主题的更多信息,请参见下文),只需切换参数并相应地调整格式字符串。
  3. 您应该使用双引号来使用变量("$F"而不是$F)来避免文件名中包含空格或其他内容的问题。
  4. 然后,如果文件以空格开头,则read会跳过这些,导致生成的变量无用。为避免这种情况,请在读取时将IFS设置为空字符串。
  5. 要仅获取目录条目的数量,您应该使用-l选项wc来仅计算(而不是单词和字符)。
  6. 使用--sort=none选项ls来避免无用的排序,从而加快速度。
  7. 使用选项-bls来转义文件名中的换行符,从而避免破坏计数。
  8. 如果您希望其他人阅读,请正确缩进代码。
  9. 结果如下:

    wcr() {
      find "$@" -type d | while IFS='' read F
        do
          printf "%5d %s\n" "$(ls --sort=none -b "$F" | wc -l)" "$F"
        done
      echo
    }
    

    我反对切换列。可能最宽的列应该在末尾(在这种情况下是文件的路径)。否则你将不得不忍受不可读的输出。但是如果你真的想要这样做,你必须做两次传递:一次确定最长的条目,另一次确定相应的格式。

答案 1 :(得分:1)

for i in $(find . -type d); do
  printf '%-10s %s\n' "$(ls $i | wc -l)" "$i"
done

您可能可以预处理输出并使用以任何顺序进行更精彩的输出,但由于路径可能变大,这样做可能更简单。