Shell Script – How to Move Files Based on File Name Expression

bashshellshell-script

I want to achieve the following using a shell script. When a script is called with a file as a parameter, it should move the file based on a portion of its name.

For example,
"Car insurance quotations_zz21.pdf" to sort into 21.Car insurance (a sub-folder of FilingCab)
"2012-09-01 Home insurance quote_zz20.pdf" to sort into 20.Home insurance (a sub-folder of FilingCab)

Logically I think it should read something like this. I did programming long long time ago, so I think have the algorithm, but do not have the commands or the syntax.

Thanks a bunch for help!


FileToMove = $1
FolderNo = (The number after zz and before a .)
ParentFolder = (~/FilingCab)
FolderList = (List of all folders in ParentFolder) 
TargetFolder = (Folder among FolderList that begins with FolderNo) - use grep?

if TargetFolder <> not empty
         cd ParentFolder
         mv FileToMove to TargetFolder
end with success
else
         do nothing
endif

end script

Best Answer

Try something like this:

#! /bin/bash

# Config variable(s)
ParentFolder="~/FilingCab"

# arg processing (minimalist :)
FileToMove="$1"

# use sed to extract folder number from filename.
FolderNo=$(echo "$FileToMove" | sed -r -e 's/.*zz([0-9]+)\.pdf/\1/')

# use find to search for subdirectories of parent folder that begin
# with the folder no followed by a '.'
TargetFolder=$(find "$ParentFolder" -maxdepth 1 -type -a -d -name "${FolderNo}.*")

NumFolders=$(echo "$TargetFolder" | wc -l)

if [ "$NumFolders" -eq 1 ] ; then 
 mv "$ParentFolder/$FileToMove" "$TargetFolder/" 
else
  echo "Error: $NumFolders beginning with "$FolderNo." found" >&2
  exit 1
fi

Note the double-quotes around all the variable names. It's always the safe/correct thing to do but in your case it's essential because the filenames and directory names you gave as examples have space characters in them.

The -maxdepth 1 in the find command only searches for direct subdirectories of $ParentFolder (i.e. ignores subdirs of subdirs). If that's not what you meant, just remove that part. This find searches for any subdirectories of $ParentFolder that begin with $FolderNo.

I'm not entirely sure what you mean by "if TargetFolder is not equal to not empty", i'm assuming you meant "is the string $TargetFolder non-empty". Ordinarily, I'd check if $TargetFolder existed and was a directory but since we're getting the directory name from a find -type d, it can only be empty or a directory. or maybe more if there's more than one beginning with "$FolderNo."

I think it's better to check if we get one and exactly one result from the find. Any other value is an error, and we can't move the file. 0 means no matching folders found. 2 or more means more than one folder beginning with "$FolderNo." was found.

The warning msg to stderr is optional. so is the exit 1, but recommended. It allows you to call this script from another script and check whether it was successful or not.

Related Question