Reputation: 1402
In Linux I'm trying to monitor all subdirectories of the current directory and output their file counts. The command I currently have is:
watch 'for FILE in `find . -maxdepth 1 -mindepth 1 -type d | grep -v "unwanted\|directories\|here"`; do echo -n $FILE " "; find $FILE -type f | wc -l; done | column -t'
This works perfectly, except occasionally I get this error,
find: `FILE_NAME': No such file or directory
Where FILE_NAME is the name of a file in one of the subdirectories.
Does anyone know why this would happen and how to fix it? Thanks!
Upvotes: 1
Views: 1949
Reputation: 7802
This only uses bash builtins (but AFAIK the only bashism is export -f, so you can use /bin/sh if you want to mangle it into an ugly, unreadable one-liner)
#!/bin/bash
myfunc(){
for DIR in "$1/"*; do
case "$DIR" in
unwanted|dirs)continue;;
*)[ -d "$DIR" ] && {
printf "%30s " "$DIR"
i=0
for FILE in "$DIR/"*; do
[ -f "$FILE" ] && i=$((i+1))
done
echo $i
};;
esac
done
}
export -f myfunc
watch myfunc "$HOME"
Note that anything that could be a file name with spaces is double quoted, to prevent trying to stat 2 directories: Program and Files instead of "Program Files". It is best practice to double quote variables that have any chance of having separators (btw you can have tabs and newline characters in file names + some really weird stuff - pretty much anything but "/" )
Upvotes: 1
Reputation: 9877
Your command does not handle spaces in filenames.
Avoid running for x in $(find)...
, or at least set IFS to $'\n'
when running the loop.
Since you only seem to care for the immediate subdirectories, you don't even need to use find
for the loop values:
watch 'for FILE in *; do [ -d "$FILE" ] && { echo -n $FILE " "; find $FILE -type f | wc -l; } done | column -t'
(you can use a more complex pattern instead of *
, or even filter with echo "$FILE" | grep
inside the loop if you need more specific matching)
Upvotes: 0