Bash: best practices for iterating directory contents to match conditions

I have the following case:

I would like to browse files in a directory $1until one of them fulfills my condition.

In detail: I would like to test the catalog about whether it contains audio files. As soon as the first audio file is found, it process_audio_dirshould take place; if there are no audio files in the directory, it process_noaudiowill happen.

My decision:

if [[ -z $(file -b "$1"/* | grep -i audio) ]]; then
  echo "there are no audio files"; process_noaudio
else
  echo "at least one audio file"; process_audio_dir
fi

file -b tells me which file is the file.

My guess, looking at it with help set -x, is that it will run file -bin all files, put the result on one line and fit that line to match. (Perhaps this is a wrong assumption).

, , ( , ), / , , , process_noaudio.

, / , , .

( ) ?

+4
3

, glob, , :

for path in "$1"/*; do
    if file -b -- "$path" | grep -qi audio; then
        printf 'Found an audio file %s\n' "$path"
        process_audio_dir
        exit
   fi
done
# since we didn't exit above, most be no audio files
printf "Didn't find any audio files\n"
process_noaudio

, , , , , , , break if, , .

, grep file, , glob , ,

file -b dir/file1 dir/file2 dir/file3 ...

grep glob "" , . , file , , . , , , - .

, find ls, , . for - . . ls

+3

,

find "$1" -maxdepth 1 -type f \
  -exec sh -c 'file -b -- "$1" | grep -qi audio' _ {} \; \
  -print \
  -quit

file , grep, . , -exec , , , , find , grep (, , -print -quit ).


, GNU

shopt -s nocaseglob # enable case-insensitive matching
while IFS= read -r -d '' filename && IFS= read -r type; do
  if [[ $type = *audio* ]]; then
    break # exit the loop with the name in "$filename" and the type in "$type"
  fi
done < <(find "$1" -type f -maxdepth 1 -exec file -b -0 -- '{}' +)
echo "Found file $filename of type $type"

file ( -exec ... {} + file), GNU -0 NUL . read, audio.

+1

API POSIX C opendir()/readdir(), . Bash.

ls Bash. - ls ( , ls . ls , ):

ls "$1" | while read f; do test -f $f && echo $f | grep -q "audio" && echo $f && break; done

Another common tool is find. Search for work gradually. The following will work for your use case of “iterating directory contents to conditions” and is a better approach than ls. It just prints the first file name found. Adjust the set exactly as you want when the condition matches:

find -maxdepth 1 -type f -exec "bash" -c "file -b '{}' | grep -qi audio" ";" -print -quit
0
source

Source: https://habr.com/ru/post/1662037/


All Articles