-1

The below script is used to check and change the owner for a single directory if the directory contains more than 4 files, How can we add multiple directories so that it would check in all the directories and in any of the directories contains more than 4 files it can change the owner

#!/bin/bash
FILE=""
DIR="/home/ec2-user/test1"
dir_files=("$DIR"/*)
if [[ "${#dir_files[@]}" -gt 4 ]] ; then
#More than 4 files change owner satha
    chown satha $DIR
elif [[ -e "${dir_files[0]}" ]] ; then
#change owner if DIR is below 4 files
    chown lohith $DIR
else
#change owner if DIR is empty
 chown lohith $DIR
fi

2 Answers2

1
#!/bin/zsh -
dirs=( $^argv(N-/) ) # those of the arguments that can  be determined to
                     # be directories after symlink resolution

for dir ($dirs) {
  files=( $dir/*(NDY5) ) # files in $dir, stopping at the 5th
  case $#files {
    (5) chown -- satha $dir;; # for > 4 files
    (0) chown -- lohith $dir;; # for no file
    (*) chown -- lohith $dir;; # anything else (1 to 4)
  }
}
0

You can create a for loop, to iterate through the directories you want stored in a variable

My structure looks like:

:~/test1$ find . | sort
.
./dir1
./dir1/dir1-a
./dir1/dir1-a/file1a-a
./dir1/dir1-a/file1a-b
./dir1/dir1-a/file1a-c
./dir1/dir1-a/file1a-d
./dir1/dir1-b
./dir1/dir1-b/file1b-a
./dir1/dir1-b/file1b-b
./dir1/dir1-b/file1b-c
./dir1/dir1-c
./dir1/dir1-c/file1c-a
./dir1/dir1-c/file1c-b
./dir1/dir1-d
./dir1/dir1-d/file1d-a
./dir1/file1-a
./dir1/file1-b
./dir2
./dir2/dir2-a
./dir2/dir2-b
./dir2/dir2-c
./test.sh

Note dir1 contains files and folders. You haven't said what you want to do with the sub-folders, or if any will exist.

#!/bin/bash

DIR=( "/home/aubs/test1/dir1" "/home/aubs/test1/dir2" )

for Item in "${DIR[@]"} do echo "Scanning $Item" COUNT_FILES=$(find "$Item" -maxdepth 1 -type f | wc -l) echo "contains $COUNT_FILES files" done

Everything you want doing on each if the items in DIR should be put between the do and done, the directory name on each iteration is $Item.

$ ./test.sh
Scanning /home/aubs/test1/dir1
contains 2 files
Scanning /home/aubs/test1/dir2
contains 0 files

Using ${#dir_files[@]} gives 6 and 3 for my test, which is clearly taking directories into account too. My example uses find "$Item" -maxdepth 1 -type f which only counts the number of files in the directory, and does not look into sub-directories. It then pipes it to wc -l which counts how many lines there are.

You also haven't taken into account if you want to take ownership of the files in the folder either.

Aubs
  • 111
  • for Item in ${DIR[*]} is a disaster waiting to happen. Use for Item in "${DIR[@]}" instead. - i.e. double-quouted and with @ instead of *. – cas Dec 19 '22 at 04:19
  • Thanks @cas, would you mind expanding on why it is a disaster waiting to happen? - I'm not great with scripting and would love to know. – Aubs Dec 19 '22 at 21:29
  • In short - because of the way shell's word-splitting happens. If any of the items in the array have spaces, tabs, newlines, etc then shell will split them into multiple tokens. e.g. a file called "hello world.txt" would be interpreted as two files "hello" and "world.txt". It's even worse if the array contains any shell meta-characters like ;, &, >, |, etc. Unquoted, the shell will interpret them as instructions, not literal strings. Your script above with sample data doesn't have any of these characters, but the real data might have. Worse, it's a bad habit to get into. – cas Dec 20 '22 at 02:23
  • From man bash: If subscript is @ or , the word expands to all members of name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word. When there are no array members, ${name[@]} expands to nothing.* – cas Dec 20 '22 at 02:25