0

By using bash script, I'm trying to detect whether a file has been created on a directory or not while running commands. Let me illustrate the problem;

#!/bin/bash

# give base directory to watch file changes
WATCH_DIR=./tmp
 
# get list of files on that directory
FILES_BEFORE= ls $WATCH_DIR

# actually a command is running here but lets assume I've created a new file there.
echo >$WATCH_DIR/filename

# and I'm getting new list of files.
FILES_AFTER= ls $WATCH_DIR  

# detect changes and if any changes has been occurred exit the program.

After that I've just tried to compare these FILES_BEFORE and FILES_AFTER however couldn't accomplish that. I've tried;

  1. comm -23 <($FILES_AFTER |sort) <($FILES_BEFORE|sort)
  2. diff $FILES_AFTER $FILES_BEFORE > /dev/null 2>&1
  3. cat $FILES_AFTER $FILES_BEFORE | sort | uniq -u

None of them gave me a result to understand there is a change or not. What I need is detecting the change and exiting the program if any. I am not really good at this bash script, searched a lot on the internet however couldn't find what I need. Any help will be appreciated. Thanks.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • What do you mean about "changed"? Created/remove files or edit files? – Saboteur Oct 06 '21 at 21:21
  • created as I mentioned on the title :) Changed means; when I compare list of files on different time, I am excepting a change on that lists aka a different file newly created. – Süleyman Sümertaş Oct 06 '21 at 21:27
  • 3
    Have you tried `echo "The files I found were: $FILES_BEFORE"` to see if you are correctly [assigning the output of a command](https://stackoverflow.com/questions/4651437/how-do-i-set-a-variable-to-the-output-of-a-command-in-bash)? – that other guy Oct 06 '21 at 21:31
  • 2
    Run your script through [Shell Check](https://www.shellcheck.net/). It will tell you exactly what @thatotherguy is alluding to, and is a great tool in general for "syntax checking" scripts. – John Kugelman Oct 06 '21 at 21:39
  • oh thank you both! I got it right now, however checking diff is still a problem. – Süleyman Sümertaş Oct 06 '21 at 21:50

3 Answers3

1

Here is how I got it to work. It's also setup up so that you can have multiple watched directories with the same script with cron. for example, if you wanted one to run every minute.

* * * * * /usr/local/bin/watchdir.sh /makepdf

and one every hour.

0 * * * * /user/local/bin/watchdir.sh /incoming

#!/bin/bash

WATCHDIR="$1"

NEWFILESNAME=.newfiles$(basename "$WATCHDIR")

if [ ! -f "$WATCHDIR"/.oldfiles ]
then
        ls -A "$WATCHDIR" > "$WATCHDIR"/.oldfiles
fi

ls -A "$WATCHDIR" > $NEWFILESNAME

DIRDIFF=$(diff "$WATCHDIR"/.oldfiles $NEWFILESNAME | cut -f 2 -d "")

for file in $DIRDIFF
do

if [ -e "$WATCHDIR"/$file ];then
        #do what you want to the file(s) here
        echo $file
fi

done

rm $NEWFILESNAME
0

Thanks to informative comments, I've just realized that I've missed the basics of bash script but finally made that work. I'll leave my solution here as an answer for those who struggle like me.:

WATCH_DIR=./tmp

FILES_BEFORE=$(ls $WATCH_DIR)

echo >$WATCH_DIR/filename

FILES_AFTER=$(ls $WATCH_DIR)

if diff <(echo "$FILES_AFTER") <(echo "$FILES_BEFORE")
then
    echo "No changes"
else
    echo "Changes"
fi

It outputs "Changes" on the first run and "No Changes" for the other unless you delete the newly added documents.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
0

I'm trying to interpret your script (which contains some errors) into an understanding of your requirements.

I think the simplest way is simply to rediect the ls command outputto named files then diff those files:

#!/bin/bash

# give base directory to watch file changes
WATCH_DIR=./tmp
 
# get list of files on that directory
ls $WATCH_DIR > /tmp/watch_dir.before

# actually a command is running here but lets assume I've created a new file there.
echo >$WATCH_DIR/filename

# and I'm getting new list of files.
ls $WATCH_DIR > /tmp/watch_dir.after

# detect changes and if any changes has been occurred exit the program.

diff -c /tmp/watch_dir.after /tmp/watch_dir.before

If the any files are modified by the 'commands', i.e. the files exists in the 'before' list, but might change, the above will not show that as a difference.

In this case you might be better off using a 'marker' file created to mark the instance the monitoring started, then use the find command to list any newer/modified files since the market file. Something like this:

#!/bin/bash

# give base directory to watch file changes
WATCH_DIR=./tmp
 
# get list of files on that directory
ls $WATCH_DIR > /tmp/watch_dir.before

# actually a command is running here but lets assume I've created a new file there.
echo >$WATCH_DIR/filename

# and I'm getting new list of files.
find $WATCH_DIR -type f -newer /tmp/watch_dir.before -exec ls -l {} \;

What this won't do is show any files that were deleted, so perhaps a hybrid list could be used.

TenG
  • 3,843
  • 2
  • 25
  • 42