2

Ive been working on a script that instantaneously detects files created in the Downloads directory then sorts them based on file extension. The issue with this however is that when downloading a file from the internet it moves the file while its downloading corrupting the file.

Is there a way i can halt the actions of the script until its done? One idea i have for instance I've noticed when downloading files from the internet i usually see a file with the .part file extension is there something i can add that when it detects this file extension loops until its gone then continue with the rest of the script?

If not im up for any suggestions just ask away if you have questions. -Thanks

#!/bin/bash

# Requires inotify-tools package
#
# Authors: oddstap && yetanothergeek
#
# This simple tool takes newly created files in the Downloads directory
# and then organizes them based on file extension.

TARGET=$HOME/Downloads
inotifywait -m -e close_write -e moved_to --format "%f" "$TARGET" \
| while read FILENAME; do

  EXT=${FILENAME##*.} # Extract file extension
  EXT=${EXT,,} # Convert to lowercase
  DEST_DIR=''

  case "$EXT" in

    # Word processor and text files
    doc|docx|odt|pdf|rtf|tex|txt|wks|wps|wpd)
      DEST_DIR="$HOME/Documents/Word_Processor_And_Text_files"
    ;;

    # Audio files
    mp3|wav|wma|mid|midi|aif|cda|mpa|ogg|wpl)
      DEST_DIR="$HOME/Music"
    ;;

    # Image files
    jpg|jpeg|png|ai|bmp|gif|ico|ps|svg|tif|tiff|psd)
      DEST_DIR="$HOME/Pictures"
    ;;

    # Video files
    avi|wmv|3g2|3gp|flv|h264|m4v|mkv|mov|mp4|mpg|mpeg|rm|swf|vob|wmv)
      DEST_DIR="$HOME/Videos"
    ;;

    # Compressed files
    7z|arj|deb|pkg|rar|rpm|gz|z|zip)
      DEST_DIR="$HOME/Documents/Compressed_Files"
    ;;

    # Disc and media files
    bin|dmg|iso|toast|vcd)
      DEST_DIR="$HOME/Documents/Disk_Images"
    ;;

    # Data and database files
    csv|dat|db|dbf|log|mdb|sav|sql|tar|xml)
      DEST_DIR="$HOME/Documents/Data_Database"
    ;;

    # Executable files
    apk|bat|cgi|pl|com|exe|gadget|jar|py|wsf)
      DEST_DIR="$HOME/Documents/Executable_File"
    ;;

    # Font files
    fnt|fon|otf|ttf)
      DEST_DIR="$HOME/Documents/Fonts"
    ;;

    # Internet related files
    asp|cer|cfm|css|htm|html|js|jsp|php|rss|xhtml)
      DEST_DIR="$HOME/Documents/Internet_files"
    ;;

    # Presentation files
    key|odp|pps|ppt|pptx)
      DEST_DIR="$HOME/Documents/Presentation"
    ;;

    # Programming files
    c|class|cpp|cs|h|java|sh|swift|vb)
      DEST_DIR="$HOME/Documents/Programming_Files"
    ;;

    # Spreadsheet files
    ods|xlr|xls|xlsx)
      DEST_DIR="$HOME/Documents/Spreadsheets"
    ;;

    # Anything else
    *)
      # TODO: handle any unrecognized files here
    ;;
  esac
  if [ "$DEST_DIR" = "" ] ; then
    # If we didn't find a place for this file, just skip it.
    continue
  fi
  # Now we should have our filename and our destination directory
  # So let's do it!
  mkdir -p "$DEST_DIR"
  chmod +w "$TARGET/$FILENAME"
  if ! [ -e "$DEST_DIR/$FILENAME" ] ; then
    mv "$TARGET/$FILENAME" "$DEST_DIR"
  else
    # Don't clobber existing files!
    # If we already have a "foo.txt", try "foo.txt.1.txt",
    # "foo.txt.2.txt", etc. If we can't find a unique name
    # after "foo.txt.99.txt" just give up -- the user can
    # deal with it later.
    N=0
    while [ $N -le 99 ] ; do
      if ! [ -e "$DEST_DIR/$FILENAME.$N.$EXT" ] ; then
        mv "$TARGET/$FILENAME" "$DEST_DIR/$FILENAME.$N.$EXT"
        break # Success!
      fi
      N=$((N+1))
    done
  fi
done
5
  • Possible duplicate of Wait for multiple files to be finished downloading
    – roaima
    Oct 18, 2019 at 10:43
  • In the possible duplicate I've suggested, I'd particularly recommend the answer with inotifywait
    – roaima
    Oct 18, 2019 at 10:44
  • 1
    @roaima, well, they are already using inotifywait... I wonder why close_write would catch an incomplete file.
    – ilkkachu
    Oct 18, 2019 at 10:55
  • @roaima took a look at the link, i didn't notice anything there that could help i also doubt this is a duplicate. but then again im new to shell scripting.
    – mr Stap
    Oct 19, 2019 at 12:18
  • @ilkkachu I thought that close_write would fix the problem but it didn't unfortunately what it will do is move the file anyway then leave a .part file which is being written to. maybe thats why its not working?
    – mr Stap
    Oct 19, 2019 at 12:22

1 Answer 1

1

I Believe i have a fix for it, luckily i was able to meet a much more talented linux user than i who is also the co-author of the script will not be giving away names since that would be rude of me but he came up with this line at the end of "| while read FILENAME; do" add this "[ -s "$TARGET/$FILENAME" ] || continue" not sure what it does since I'm a novice but now the script will wait until files are done downloading before moving them.

#!/bin/bash

# Requires inotify-tools package
#
# Authors: oddstap && yetanothergeek
#
# This simple tool takes newly created files in the Downloads directory
# and then organizes them based on file extension.

TARGET=$HOME/Downloads
inotifywait -m -e close_write -e moved_to --format "%f" "$TARGET" \
| while read FILENAME; do

  [ -s "$TARGET/$FILENAME" ] || continue

  EXT=${FILENAME##*.} # Extract file extension
  EXT=${EXT,,} # Convert to lowercase
  DEST_DIR=''

  case "$EXT" in

    # Word processor and text files
    doc|docx|odt|pdf|rtf|tex|txt|wks|wps|wpd)
      DEST_DIR="$HOME/Documents/Word_Processor_And_Text_files"
    ;;

    # Audio files
    mp3|wav|wma|mid|midi|aif|cda|mpa|ogg|wpl)
      DEST_DIR="$HOME/Music"
    ;;

    # Image files
    jpg|jpeg|png|ai|bmp|gif|ico|ps|svg|tif|tiff|psd)
      DEST_DIR="$HOME/Pictures"
    ;;

    # Video files
    avi|wmv|3g2|3gp|flv|h264|m4v|mkv|mov|mp4|mpg|mpeg|rm|swf|vob|wmv)
      DEST_DIR="$HOME/Videos"
    ;;

    # Compressed files
    7z|arj|deb|pkg|rar|rpm|gz|z|zip)
      DEST_DIR="$HOME/Documents/Compressed_Files"
    ;;

    # Disc and media files
    bin|dmg|iso|toast|vcd)
      DEST_DIR="$HOME/Documents/Disk_Images"
    ;;

    # Data and database files
    csv|dat|db|dbf|log|mdb|sav|sql|tar|xml)
      DEST_DIR="$HOME/Documents/Data_Database"
    ;;

    # Executable files
    apk|bat|cgi|pl|com|exe|gadget|jar|py|wsf)
      DEST_DIR="$HOME/Documents/Executable_File"
    ;;

    # Font files
    fnt|fon|otf|ttf)
      DEST_DIR="$HOME/Documents/Fonts"
    ;;

    # Internet related files
    asp|cer|cfm|css|htm|html|js|jsp|php|rss|xhtml)
      DEST_DIR="$HOME/Documents/Internet_files"
    ;;

    # Presentation files
    key|odp|pps|ppt|pptx)
      DEST_DIR="$HOME/Documents/Presentation"
    ;;

    # Programming files
    c|class|cpp|cs|h|java|sh|swift|vb)
      DEST_DIR="$HOME/Documents/Programming_Files"
    ;;

    # Spreadsheet files
    ods|xlr|xls|xlsx)
      DEST_DIR="$HOME/Documents/Spreadsheets"
    ;;

    # Anything else
    *)
      # TODO: handle any unrecognized files here
    ;;
  esac
  if [ "$DEST_DIR" = "" ] ; then
    # If we didn't find a place for this file, just skip it.
    continue
  fi
  # Now we should have our filename and our destination directory
  # So let's do it!
  mkdir -p "$DEST_DIR"
  chmod +w "$TARGET/$FILENAME"
  if ! [ -e "$DEST_DIR/$FILENAME" ] ; then
    mv "$TARGET/$FILENAME" "$DEST_DIR"
  else
    # Don't clobber existing files!
    # If we already have a "foo.txt", try "foo.txt.1.txt",
    # "foo.txt.2.txt", etc. If we can't find a unique name
    # after "foo.txt.99.txt" just give up -- the user can
    # deal with it later.
    N=0
    while [ $N -le 99 ] ; do
      if ! [ -e "$DEST_DIR/$FILENAME.$N.$EXT" ] ; then
        mv "$TARGET/$FILENAME" "$DEST_DIR/$FILENAME.$N.$EXT"
        break # Success!
      fi
      N=$((N+1))
    done
  fi
done

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.