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).

  • You are missing spaces in your if. It is if [ cmp --silent $y $new != null ]. – guillermo chamorro Aug 19 '19 at 19:21
  • @guillermochamorro Now it says that I've got too many arguments.. – Sir Muffington Aug 19 '19 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? – Sir Muffington Aug 19 '19 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??? – Sir Muffington Aug 19 '19 at 20:03
  • 1
    Please take a look: shellcheck.net – Cyrus Aug 19 '19 at 21:06
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
  • 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? – Sir Muffington Aug 20 '19 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 '19 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 '19 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. – Sir Muffington Aug 20 '19 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 '19 at 14:26

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.