diff --git a/simple_backup b/simple_backup index 8713e3f..99b7490 100755 --- a/simple_backup +++ b/simple_backup @@ -15,7 +15,7 @@ #You should have received a copy of the GNU General Public License #along with this program. If not, see . -#Version 1.1 +#Version 1.2 #Simple backup script. Reads options, sources and destination from a configuration file or standard input #Help function @@ -74,156 +74,68 @@ function read_conf { fi - while read line - do - #Ignore comments and empty lines - if [[ $line == \#* || $line == "" ]]; then - continue - else - #Get option name and values for the current line - var=$(echo "$line" | cut -d"=" -f1) + #Create temporary files + INPUTS=$(mktemp) + EXCLUDE=$(mktemp) + BACKUP=$(mktemp) + NKEEP=$(mktemp) - case "$var" in - #Files/folders to backup - inputs) - #Create a temporary file to store inputs - INPUTS=$(mktemp) - tmp=$(echo "$line" | cut -d"=" -f2) - n=$(echo "$tmp" | awk -F ',' '{print NF}') #Files/folders must be separated with commas - i=1 - #j=1 - n_in=0 + #Parse the configuration file + awk -v INPUTS="$INPUTS" -v EXCLUDE="$EXCLUDE" -v BACKUP="$BACKUP" \ + -v NKEEP="$NKEEP" -v UHOME="$HOME/" -F '[=,]' \ + '$1=="inputs" { for ( i=2; i<=NF; i++ ) { sub(/^~\//,UHOME,$i); print $i > INPUTS } } + $1=="backup_dir" { sub(/^~\//,UHOME,$2); print $2 > BACKUP } + $1=="exclude" { for ( i=2; i<=NF; i++ ) { sub(/^~\//,UHOME,$i); print $i > EXCLUDE } } + $1=="keep" { if ( $2 != NULL ) { print $2 > NKEEP } }' $CONFIG - #Read each input and save it to the INPUTS file - while [[ $i -le $n ]] - do - input=$(echo "$tmp" | cut -d"," -f$i) - input=$(echo "$input" | tr -d \"\') + BACKUP_DEV=$(cat $BACKUP) + KEEP=$(cat $NKEEP) + + rm "$BACKUP" + rm "$NKEEP" - if [[ "$input" =~ ^~/ ]]; then - input=$(echo ${input/\~/$HOME}) - fi + if [[ -z "$BACKUP_DEV" || ! -d "$BACKUP_DEV" ]]; then + #If the backup directory is not set or doesn't exist, exit + echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log + echo "Error: Output folder \"$BACKUP_DEV\" not found" | tee -a $HOME/.simple_backup/errors.log + #If libnotify is installed, show desktop notification that backup failed + ! command -v notify-send > /dev/null 2>&1 || DISPLAY=:0.0 notify-send -u low -t 10000 "Backup failed" - if [[ ! -e "$input" ]]; then - #Warn the user if an input doesn't exist - echo "Warning: input \"$input\" not found. Skipping" | tee -a $HOME/.simple_backup/warning.log - else - n_in=$((n_in+1)) - fi - - echo "$input" >> $INPUTS - - i=$((i+1)) - done - - ;; - - #Directory where the backup is saved - backup_dir) - BACKUP_DEV=$(echo "$line" | cut -d"=" -f2) - BACKUP_DEV=$(echo "$BACKUP_DEV" | tr -d \"\') - - if [[ "$BACKUP_DEV" =~ ^~/ ]]; then - BACKUP_DEV=$(echo ${BACKUP_DEV/\~/$HOME}) - fi - - if [[ -z "$BACKUP_DEV" ]]; then - #If the backup directory is not set, exit - echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log - echo "Error: No backup folder set in configuration file" | tee -a $HOME/.simple_backup/errors.log - #If libnotify is installed, show desktop notification that backup failed - ! command -v notify-send > /dev/null 2>&1 || DISPLAY=:0.0 notify-send -u low -t 10000 "Backup failed" - - if [[ -f $HOME/.simple_backup/simple_backup.log.old ]]; then - rm -f $HOME/.simple_backup/simple_backup.log.old - fi - - if [[ -f $HOME/.simple_backup/errors.log.old ]]; then - rm -f $HOME/.simple_backup/errors.log.old - fi - - if [[ -f $HOME/.simple_backup/warnings.log.old ]]; then - rm -f $HOME/.simple_backup/warnings.log.old - fi - - exit 1 - fi - - if [[ ! -d "$BACKUP_DEV" ]]; then - #If the backup directory doesn't exist, exit - echo "$(date): Backup failed (see errors.log)" >> $HOME/.simple_backup/simple_backup.log - echo "Error: Output folder \"$BACKUP_DEV\" not found" | tee -a $HOME/.simple_backup/errors.log - #If libnotify is installed, show desktop notification that backup failed - ! command -v notify-send > /dev/null 2>&1 || DISPLAY=:0.0 notify-send -u low -t 10000 "Backup failed" - - if [[ -f $HOME/.simple_backup/simple_backup.log.old ]]; then - rm -f $HOME/.simple_backup/simple_backup.log.old - fi - - if [[ -f $HOME/.simple_backup/errors.log.old ]]; then - rm -f $HOME/.simple_backup/errors.log.old - fi - - if [[ -f $HOME/.simple_backup/warnings.log.old ]]; then - rm -f $HOME/.simple_backup/warnings.log.old - fi - - exit 1 - fi - - BACKUP_DIR=$BACKUP_DEV/simple_backup - DATE=$(date +%Y-%m-%d-%H:%M) - - #Create the backup subdirectory using date - if [[ ! -d "$BACKUP_DIR" ]]; then - mkdir -p "$BACKUP_DIR/$DATE" - else - #If previous backup(s) exist(s), save link to the last backup - LAST_BACKUP=$(readlink -f "$BACKUP_DIR/last_backup") - mkdir "$BACKUP_DIR/$DATE" - fi - - #Set the backup directory variable to the newly created subfolder - BACKUP_DIR="$BACKUP_DIR/$DATE" - ;; - - #Files/directories/patterns to exclude from backup - exclude) - #Create temp file to store exclude patterns - EXCLUDE=$(mktemp) - temp=$(echo "$line" | cut -d"=" -f2) - i=1 - n=$(echo "$temp" | awk -F ',' '{print NF}') #Exclude patterns must be separated by commas - - #Read each exclude pattern and save it in the temp file - while [[ $i -le $n ]] - do - var=$(echo "$temp" | cut -d"," -f$i) - var=$(echo "$var" | tr -d \"\') - - if [[ "$var" =~ ^~/ ]]; then - var=$(echo ${var/\~/$HOME}) - fi - - echo "$var" >> $EXCLUDE - i=$((i+1)) - done - ;; - - #Number of old backups to keep - keep) - KEEP=$(echo "$line" | cut -d"=" -f2) - ;; - - #Unrecognized options - *) - #Skip unrecognised options - echo "$(date): Warning: option \"$var\" not recognised. Skipping" >> $HOME/.simple_backup/warnings.log - ;; - esac + if [[ -f $HOME/.simple_backup/simple_backup.log.old ]]; then + rm -f $HOME/.simple_backup/simple_backup.log.old fi - done<"$CONFIG" + if [[ -f $HOME/.simple_backup/errors.log.old ]]; then + rm -f $HOME/.simple_backup/errors.log.old + fi + + if [[ -f $HOME/.simple_backup/warnings.log.old ]]; then + rm -f $HOME/.simple_backup/warnings.log.old + fi + + rm "$INPUTS" + rm "$EXCLUDE" + + exit 1 + fi + + BACKUP_DIR=$BACKUP_DEV/simple_backup + DATE=$(date +%Y-%m-%d-%H:%M) + + #Create the backup subdirectory using date + if [[ ! -d "$BACKUP_DIR" ]]; then + mkdir -p "$BACKUP_DIR/$DATE" + else + #If previous backup(s) exist(s), save link to the last backup + LAST_BACKUP=$(readlink -f "$BACKUP_DIR/last_backup") + mkdir "$BACKUP_DIR/$DATE" + fi + + #Set the backup directory variable to the newly created subfolder + BACKUP_DIR="$BACKUP_DIR/$DATE" + + n_in=$(cat $INPUTS | wc -l) + return } @@ -231,6 +143,9 @@ function read_conf { function parse_options { i=1 n_in=0 + + #Create a temporary file to store inputs + INPUTS=$(mktemp) #Create temp file to store exclude patterns EXCLUDE=$(mktemp) @@ -254,12 +169,13 @@ function parse_options { mv -f $HOME/.simple_backup/warnings.log.old $HOME/.simple_backup/warnings.log fi + rm $INPUTS + rm $EXCLUDE + exit 0 ;; -i | --input) - #Create a temporary file to store inputs - INPUTS=$(mktemp) while [[ "$#" -gt 1 && ! "$2" =~ ^- ]] do @@ -496,9 +412,9 @@ if [[ ! -z "$INPUTS" ]]; then fi if [[ -z "$LAST_BACKUP" ]]; then - rsync -acrv -H -X -R --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log" + rsync -acrv -H -X -R --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" --ignore-missing-args >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log" else - rsync -acrv -H -X -R --link-dest="$LAST_BACKUP" --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log" + rsync -acrv -H -X -R --link-dest="$LAST_BACKUP" --exclude-from="$EXCLUDE" --files-from="$INPUTS" / "$BACKUP_DIR" --ignore-missing-args >> "$HOME/.simple_backup/simple_backup.log" 2>> "$HOME/.simple_backup/errors.log" fi #Update the logs