Steve Scrimpshire Posted February 27, 2005 Report Share Posted February 27, 2005 (edited) I have this script and I want to make the options -i /path/to/dir and -o /path/to/dir mandatory. This is how I've done it (yes, I know there's already rsync and it probably does what I'm doing better): #/bin/bash # Copyright 2005 Steve Scrimpshire (fibonacci@semperphi.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA function funchelp(){ echo "Usage: $0 -i /path/to/first/dir -o /path/to/second/dir" echo " -v Be verbose" echo " -h See this help message" exit; } # We need arguments. Can't run the script not knowing what the two directories are. if [[ ! $@ ]] then echo -n "Enter the full path to the first dir: " read indir echo -n "Enter the full path to the second dir: " read outdir fi # Check what options were passed while getopts "hi:o:v" option; do case ${option} in i) indir=${OPTARG};; # first o) outdir=${OPTARG};; # second v) verbose="1";; h|*) scripthelp="1";; esac done if [ $scripthelp ] then funchelp fi # Didn't have the -i option. Give them another chance to enter it if [ ! $indir ] then echo -n "Enter the full path to the first dir: " read indir fi # Didn't have the -o option. Give them another chance to enter it if [ ! $outdir ] then echo -n "Enter the full path to the second dir: " read outdir fi # They had three chances to enter the directories. Complain and exit if [ -z $indir -o -z $outdir ] then funchelp fi if [ ! -d $indir -a ! -d $outdir ] then echo "Neither one of those directories exists. Are you nuts?" exit fi # Directory passed by -i does not exist or is not a directory if [ ! -d $indir ] then echo "$indir does not exist or does not describe the path to a directory. Would you like to create it? (y/N):" read create if [[ $create == "y" ]] then if [ -e $indir ] then echo "I'm sorry, but there is already a file with that name, so I can't create the directory. I have to go now." exit fi mkdir $indir let "created = 1" else exit fi fi # Directory passed by -o does not exist or is not a directory if [ ! -d $outdir ] then if [[ $created == "1" ]] then echo "$outdir does not exist or does not describe the path to a directory." exit else echo "$outdir does not exist or does not describe the path to a directory. Would you like to create it? (y/N):" read create if [[ $create == "y" ]] then if [ -e $outdir ] then echo "I'm sorry, but there is already a file with that name, so I can't create the directory. I have to go now." exit fi mkdir $outdir else exit fi fi fi # They entered the same directory for both -i and -o if [[ $indir == "$outdir" ]] then echo "Those two entries are the same directory...come back when you're serious." exit; fi # We need the the field separator to be newline and not space old_IFS=$IFS IFS=$'\n' cd $outdir # Change directory to the second directory usbdirs=( $(tree -difa) ) # Grab the full path to all the subdirectories into the array $usbdirs element_count=${#usbdirs[@]} # How many elements in the array? index=0 # Initialize the counter while [ "$index" -lt "$element_count" ] # We want to loop over the array, stopping when we reach the last element do if [ ${usbdirs[$index]} != "" ] # $(tree -dif) grabs blank lines, but they are not directories, so ignore them then if [ -d ${usbdirs[$index]} ] # $(tree -dif) also grabs a line with the total # of directories, but it is not a dir then tester="${usbdirs[$index]}" # Simplify the variable for use in the substitution testerz="${tester//.\//$(pwd)/}" # The 'full path' from $(tree -dif) replaces pwd with . so set it back if [ ${usbdirs[$index]} == "." ] then testerz="${tester//./$(pwd)}" fi testerZ="${tester//.\//}" if [ ! -e "$indir/$testerZ" ] then if [ $verbose ] then echo "$testerz exists, but $indir/$testerZ does not, so I will create $indir/$testrZ" echo "Making directory $indir/$testerZ" fi mkdir "$indir/$testerZ" if [ $verbose ] then echo "Done" fi fi if [ $verbose ] then echo "cd-ing to $testerz" fi cd "$testerz" usbfiles="$(ls -A)"; for usbname in $usbfiles do if [[ "$usbname" != *.old ]] then if [ -f "$usbname" ] then mvdir=$indir/$testerZ/$(basename "$usbname"); if [ -e $mvdir ] then if [ $mvdir -nt "$usbname" ] then if [ $verbose ] then echo "$mvdir is newer than $usbname, so I am going to cp $mvdir to $usbname." echo "Removing ${usbname}.old}" fi rm -f "${usbname}.old" if [ $verbose ] then echo "Done." echo "Moving $usbname to ${usbname}.old for a backup." fi mv "$usbname" "${usbname}.old" if [ $verbose ] then echo "Done." echo "Copying $mvdir to $usbname, preserving permissions." fi cp -p "$mvdir" "$usbname" if [ $verbose ] then echo "Done." fi elif [ $mvdir -ot "$usbname" ] then if [ $verbose ] then echo "$usbname is newer than $mvdir, so I am going to cp $usbname to $mvdir." echo "Removing ${mvdir}.old" fi rm -f "${mvdir}.old" if [ $verbose ] then echo "Done." echo "Moving $mvdir to ${mvdir}.old for a backup." fi mv "$mvdir" "${mvdir}.old" if [ $verbose ] then echo "Done" echo "Copying $usbname to $mvdir" fi cp -p "$usbname" "$mvdir" if [ $verbose ] then echo "Done" fi else if [ $verbose ] then echo "These two files are the same age, so I will do nothing." fi fi else if [ $verbose ] then echo "$mvdir does not exist, so I'll just copy $usbname to $mvdir" fi cp -p "$usbname" "$mvdir" if [ $verbose ] then echo "Done" fi fi fi else if [ $verbose ] then echo "$usbname ended in .old, so I skipped it. Duh. Don't want to have a bunch of *.old.old.old files hanging around." fi fi done fi fi cd $outdir let "index = $index + 1" done cd $indir localdirs=( $(tree -difa) ) element_count=${#localdirs[@]} index=0 while [ "$index" -lt "$element_count" ] do if [ ${localdirs[$index]} != "" ] then if [ -d ${localdirs[$index]} ] then tester="${localdirs[$index]}" testerz="${tester//.\//$(pwd)/}" if [ ${localdirs[$index]} == "." ] then testerz="${tester//./$(pwd)}" fi testerZ="${tester//.\//}" # testerZ="${tester//^./}" if [ ! -e "$outdir/$testerZ" ] then if [ $verbose ] then echo "$testerz exists, but $outdir/$testerZ does not, so I will create $outdir/$testrZ" echo "Making directory $outdir/$testerZ" fi mkdir "$outdir/$testerZ" if [ $verbose ] then echo "Done" fi fi if [ $verbose ] then echo "cd-ing to $testerz" fi cd "$testerz" localfiles="$(ls -A)"; for localname in $localfiles do if [[ "$localname" != *.old ]] then if [ -f "$localname" ] then mvdir=$outdir/$testerZ/$(basename "$localname"); if [ -e $mvdir ] then if [ $mvdir -nt "$localname" ] then if [ $verbose ] then echo "$mvdir is newer than $localname, so I am going to cp $mvdir to $localname." echo "Removing ${localname}.old}" fi rm -f "${localname}.old" if [ $verbose ] then echo "Done." echo "Moving $localname to ${localname}.old for a backup." fi mv "$localname" "${localname}.old" if [ $verbose ] then echo "Done." echo "Copying $mvdir to $localname, preserving permissions." fi cp -p "$mvdir" "$localname" if [ $verbose ] then echo "Done." fi elif [ $mvdir -ot "$localname" ] then if [ $verbose ] then echo "$localname is newer than $mvdir, so I am going to cp $localname to $mvdir." echo "Removing ${mvdir}.old" fi rm -f "${mvdir}.old" if [ $verbose ] then echo "Done." echo "Moving $mvdir to ${mvdir}.old for a backup." fi mv "$mvdir" "${mvdir}.old" if [ $verbose ] then echo "Done" echo "Copying $localname to $mvdir" fi cp -p "$localname" "$mvdir" if [ $verbose ] then echo "Done" fi else if [ $verbose ] then echo "These two files are the same age, so I will do nothing." fi fi else if [ $verbose ] then echo "$mvdir does not exist, so I'll just copy $usbname to $mvdir" fi cp -p "$localname" "$mvdir" if [ $verbose ] then echo "Done" fi fi fi else if [ $verbose ] then echo "$localname ended in .old, so I skipped it. Duh. Don't want to have a bunch of *.old.old.old files hanging around." fi fi done fi fi cd $indir let "index = $index + 1" done IFS=$old_IFS Is there a better or more correct way of doing this? Edited February 27, 2005 by Steve Scrimpshire Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted February 28, 2005 Report Share Posted February 28, 2005 IMHO, the getopts+check thing is OK. Yves. Quote Link to comment Share on other sites More sharing options...
Steve Scrimpshire Posted February 28, 2005 Author Report Share Posted February 28, 2005 Thanks, Yves. It actually works out for me this way, because I've been playing around with it and I have made it so that if you don't have those two options, it asks you to enter them at the cli. (I even made it so that if one of the directories doesn't exist, it'll ask if you want to create it.) Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted March 1, 2005 Report Share Posted March 1, 2005 You're welcome! I didn't help in any way, as you've already got things rights :) BTW, be carefull of statements like that: if [ -z $indir -o -z $outdir ]. You should use a lot more quotes, because if indir or outdir indeed IS empty, bash will either complain, or not work as expected, since $indir or $outdir is replaced by nothing... Yves. Quote Link to comment Share on other sites More sharing options...
Steve Scrimpshire Posted March 1, 2005 Author Report Share Posted March 1, 2005 Thanks again. I usually quote everything, even when I don't have to. Got sloppy with this one, because it was making me angry. Merci encore, mon ami. (I remember a little French...lol...Je parles francais un peu. Probably poor grammar and I know I'm missing French characters.) Quote Link to comment Share on other sites More sharing options...
theYinYeti Posted March 1, 2005 Report Share Posted March 1, 2005 Me too :lol: When I program a main code, inside of which a private function is called, I often don't even trust the main code from inside the function, for giving parameters as they should be; I often simply take every case into account... I must be mad. Yves Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.