0

I have the following script:

#!/bin/bash
y=$(ls -t ./pics/0/*.png | head -n 2 | tail -n 1)
new=$(ls -t ./pics/0/*.png | head -n 1)
while true
do
 if cmp --silent "$y" "$new" ; then
y=$(ls -t ./pics/0/*.png | head -n 1)
    base64 $y | tr -d '\n' | sed '$ a \'
new=$(ls -t ./pics/0/*.png | head -n 1)
 fi
done

What am I doing wrong? To be clear my goal is to compare whether the newest file is different from the previous newest file and only if it is generate a unique BASE64 to STDOUT (meaning it should be printed only ONCE).

15
  • You are missing spaces in your if. It is if [ cmp --silent $y $new != null ]. Aug 19, 2019 at 19:21
  • @guillermochamorro Now it says that I've got too many arguments.. Aug 19, 2019 at 19:24
  • @steeldriver this code works, but the script prints out multiple duplicate base64 strings, I probably made a logical error in doing the script then? any clue how to fix it so that prints unique base64 every time a file is changed? Aug 19, 2019 at 19:32
  • Removing the --silent flag seems to reduce the number of occurrences of base64 strings to only 3-4 per second, when a new file is added every second. Is this a bug??? Aug 19, 2019 at 20:03
  • 1
    Please take a look: shellcheck.net
    – Cyrus
    Aug 19, 2019 at 21:06

1 Answer 1

0

Please note that the following snippet will NOT work with filenames containing spaces, tabs or newlines.

To find out more about the find-command used here, please reference https://unix.stackexchange.com/a/240424/364705

#!/bin/bash
lastrun=''
while true; do
  read -r newer older <<< \
    $(find . -type f -exec stat -c '%Y %n' {} \; \
    | sort -nr \
    | awk 'NR==1,NR==2 {print $2}'\
    | xargs )

  if [ "$newer" == "$lastrun" ]; then
    :
  else
    if ! cmp "$newer" "$older" > /dev/null ; then
      base64 "$newer"| tr -d '\n' | sed '$ a \'
      lastrun="$newer"
    fi
  fi
done

And a solution using inotify-wait:

#!/bin/bash
lastfile=''
inotifywait -m /path/to/somewhere -e close -e moved_to |
while read path action file; do
  if [ "$lastfile" != '' ];then
    if ! cmp "${path}$file" "${path}${lastfile}" > /dev/null  ; then
    base64 "${path}${file}"
    fi
  fi
    lastfile="$file"
done
9
  • This works. However, when the file amount in the folder goes around over 1000 it appears to skip 1-3 files per second. Is this a performance limitation of find? Aug 20, 2019 at 14:00
  • Could be a shell-script isn't fast enough if the files are coming quickly. If you do not have any subdirectories in the directory where you are running this, then you can drop the find..-exec and just do stat -c '%Y %n' * instead. That should be faster.
    – markgraf
    Aug 20, 2019 at 14:06
  • If that still isn't fast enough, maybe look into inotifywait to trigger an action whenever a file is created/moved_to your directory.
    – markgraf
    Aug 20, 2019 at 14:22
  • It doesn't appear to be working without the find part. I already wrote a prototype for inotifywait, but still need to format it properly. Aug 20, 2019 at 14:23
  • $(stat -c '%Y %n' * | sort -nr ... instead of $(find . -type f -exec stat -c '%Y %n' {} \; | sort -nr .... But only if there are no subdirs.
    – markgraf
    Aug 20, 2019 at 14:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .