I have the following script:

y=$(ls -t ./pics/0/*.png | head -n 2 | tail -n 1)
new=$(ls -t ./pics/0/*.png | head -n 1)
while true
 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)

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 ]. Aug 19 '19 at 19:21
  • @guillermochamorro Now it says that I've got too many arguments.. 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? 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??? Aug 19 '19 at 20:03
  • 1
    Please take a look: shellcheck.net
    – Cyrus
    Aug 19 '19 at 21:06

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

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
    if ! cmp "$newer" "$older" > /dev/null ; then
      base64 "$newer"| tr -d '\n' | sed '$ a \'

And a solution using inotify-wait:

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}"
  • 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 '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. 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.