0

I need to write a Bash script to check if there are any new folders in a path, if yes do something and if not then simply exit.

My thinking is to create a text file to keep track of all old folders and do a diff, if there something new then perform action. Please help me achieve this:

I've tried to use two file tracking but I don't think I've got this right.

The /tmp/ folder has multiple sub folders

#/bin/sh
BASEDIR=/tmp/
cd $BASEDIR
ls -A $BASEDIR >> newfiles.txt
DIRDIFF=$(diff oldfiles.txt newfiles.txt | cut -f 2 -d "")
for file in $DIRDIFF
do
  if [ -e $BASEDIR/$file ]
  then echo $file
  fi
done
nick
  • 99
  • 7
  • The [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) needs to begin with exactly the two characters `#!`. The path `/bin/sh` causes your script to be run by `sh`, not Bash; see also [Difference between sh and bash](https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash) (though as your script uses on Bash-only features, it should still work fine, though it doesn't do what you say you want). – tripleee Oct 15 '21 at 12:43

2 Answers2

1

Let's assume you are interested in sub-directories only. Let's assume too that you do not have directory names with newlines in them.

Do not process ls output, it is for humans only. Prefer find. Then, simply sort the old and new lists with sort and compare them with comm, keeping only the lines found in the new list but not in the old list (man comm will tell you why the -13 option does this). In the following the do something is just echo, replace by whatever is needed:

#!/bin/sh
BASEDIR=/tmp/
cd "$BASEDIR"
find . -type d | sort > new.txt
if [ -f old.txt ]; then
    comm -13 old.txt new.txt | while IFS= read -r name; do
        echo "$name"
    done
fi
mv new.txt old.txt

This will explore the complete hierarchy under the starting point, and consider any directory. If you do not want to explore the complete hierarchy under the starting point but only the current level:

find . -maxdepth 1 -type d | sort > new.txt
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
1

Generally don't use ls in scripts. Here is a simple refactoring which avoids it.

#!/bin/sh
printf '%s\n' /tmp/.[!.]* /tmp/* >newfiles.txt
if cmp -13 oldfiles.txt newfiles.txt | grep .; then
    rc=0
    rm newfiles.txt
else
    rc=$?
    mv newfiles.txt oldfiles.txt
fi
exit "$rc"

Using comm instead of diff simplifies processing somewhat (the wildcard should expand the files in sorted order, so the requirement for sorted input will be satisfied) and keeping the files in the current directory (instead of in /tmp) should avoid having the script trigger itself. The output from comm will be the new files, so there is no need to process it further. The grep . checks if there are any output lines, so that we can set the exit status to reflect whether or not there were new entries.

Your script looks for files, not directories. If you really want to look for new directories, add a slash after each wildcard expression:

printf '%s\n' /tmp/.[!.]*/ /tmp/*/ >newfiles.txt

This will not notice if an existing file or directory is modified. Probably switch to inotifywait if you need anything more sophisticated (or perhaps even if this is all you need).

tripleee
  • 175,061
  • 34
  • 275
  • 318