Cobra1117
Cobra1117

Reputation: 1402

Linux watch command "no such file or directory"

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

Answers (2)

technosaurus
technosaurus

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

Sir Athos
Sir Athos

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

Related Questions