0

I have directory contains many subdirectories and each subdirectory has a couple of files (interested only to files with .ar extension). Now, I need to loop through each subdirectory and check, for example, if the number of the files = 4 then do something to these files, go back to the second subdirectory check the files if = 3 then do another command on them. Note that, I have much-complicated conditions I have to apply on the if statement.

something similar to this

dir=$1

for sub_dir in $dir; do
    if the number of files in $sub_dir = 4; then
        do something or command line 
    if the number of files in $sub_dir = 3; then
       do another command
    if the number of files in $sub_dir < 3; then
    escape them

    fi
done

I need a template for a similar process.

2

Assuming that the subdirectories are located directly under the top directory:

#!/bin/sh

topdir="$1"

for dir in "$topdir"/*/; do
    set -- "$dir"/*.ar

    if [ "$#" -eq 1 ] && [ ! -f "$1" ]; then
        # do things when no files were found
        # "$1" will be the pattern "$dir"/*.ar with * unexpanded
    elif [ "$#" -lt 3 ]; then
        # do things when less than 3 files were found
        # the filenames are in "$@"        
    elif [ "$#" -eq 3 ]; then
        # do things when 3 files were found
    elif [ "$#" -eq 4 ]; then
        # do things when 4 files were found
    else
        # do things when more than 4 files were found
    fi
done

Or, using case:

#!/bin/sh

topdir="$1"

for dir in "$topdir"/*/; do
    set -- "$dir"/*.ar

    if [ "$#" -eq 1 ] && [ ! -f "$1" ]; then
        # no files found
    fi

    case "$#" in
        [12])
            # less than 3 files found
            ;;
        3)
            # 3 files found
            ;;
        4)
            # 4 files found
            ;;
        *)
            # more than 4 files found
    esac
done

The branches of the code that needs the filename uses "$@" to refer to all filenames in a subdirectory, or "$1", "$2" etc. to refer to the individual files. The filenames will be pathnames including the $topdir directory at the start.

1

You can do something like this:

dir=$1

subdirectories = $(find $dir -type d) # find only subdirectories in dir

for subdir in $subdirectories
do
   n_files=$(find $subdir -maxdepth 1 -type f | wc -l) # find ordinary files in subdir and get it quantity

   if [ $n_files -eq 4 ]
   then
      do_something_4
   fi

   if [ $n_files -eq 3 ]
   then
      do_something_3
   fi

   if [ $n_files -lt 3 ]
   then
      do_something_else
   fi
done 
  • Of cause you can replace series of if .. then with case operator and put -name '*.ar' to find filter in n_files string. – Yurij Goncharuk Mar 28 '18 at 23:50
  • I couldn't understand this comment and it seems important because I need to specify only *.ar files to be chosen. would you please re-explain it more clear for me? – abubakr yagob Mar 29 '18 at 0:12
  • 2
    You can change the second find command to include -name *.ar so that the name is checked too. I.e., find $subdir -name *.ar -maxdepth 1 -type f – melds Mar 29 '18 at 0:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.