quickbug
quickbug

Reputation: 4848

print recursively the number of files in folders

I struggled for hours to get this uggly line to work

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

Here is the result

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

My first question is: how can I write it smarter?

Second question: I would like the names printed before the counts but I dont know how to tabulate the outputs, so I cannot do better than this:

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

Upvotes: 0

Views: 86

Answers (2)

Reinstate Monica Please
Reinstate Monica Please

Reputation: 11593

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

You probably could pre-process the output and use column to make some fancier output with whatever order, but since the path can get big, doing this is probably simpler.

Upvotes: 1

Alfe
Alfe

Reputation: 59436

  1. I don't see what that find $F -maxdepth 0 shall be good for, so I would just strip it.
  2. Also, if a filename contains a %, you are in trouble if you use it as the format string to printf, so I'd add an explicit format string. And I combined the two printfs. To switch the columns (see also below for more on this topic), just switch the arguments and adapt the format string accordingly.
  3. You should use double quotes around using variables ("$F" instead of $F) to avoid problems with filenames with spaces or other stuff in them.
  4. Then, if a file starts with spaces, your read would skip those, rendering the resulting variable useless. To avoid that, set IFS to an empty string for the time of the read.
  5. To get only the number of directory entries, you should use option -l for wc to only count the lines (and not also words and characters).
  6. Use option --sort=none to ls to speed up things by avoiding useless sorting.
  7. Use option -b to ls to escape newline characters in file names and thus avoid breaking of counting.
  8. Indent your code properly if you want others to read it.

This is the result:

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

I'd object to switching the columns. The potentially widest column should be at the end (in this case the path to the file). Otherwise you will have to live with unreadable output. But if you really want to do this, you'd have to do two passes: One to determine the longest entry and a second to format the output accordingly.

Upvotes: 3

Related Questions