# Bash script to back up files

I am new to bash, so I'm a bit lost with this script I made to backup some directories from the local machine into a NAS. The NAS will contain only a certain number of backed up files, so before copying a new one I delete the oldest of the existing.

First of all the script defines all the paths, directory and file names into variables

# Defines directories
ORIGEN='/Library/path-to-directories/'
DESTINAS='/Volumes/path-to-backup/'
DESTITAR='/Library/path-to-temp/'

# Defines names of the files and folders to delete (OLDDIR) and copy (NEWDIR)
OLDTAR=/bin/ls /Volumes/path-to-backup/ | head -n 1
NEWDIR=/bin/ls /Library/path-to-directories/ | tail -n 1


Then using the variable names it: Creates a tar compressed file from the original directory. The tar file is kept in a separate, temporary directory.

/usr/bin/sudo /usr/bin/tar -czf "$DESTITAR$NEWDIR.tgz" "$ORIGEN$NEWDIR"


Deletes the older of the tar files from the NAS:

/usr/bin/sudo /bin/rm $DESTINAS$OLDTAR


Copies the tar file into the NAS:

/usr/bin/sudo /bin/cp -Rp "$DESTITAR$NEWDIR.tgz" $DESTINAS  Deletes the tar file from the temp directory: /usr/bin/sudo /bin/rm -f "$DESTITAR$NEWDIR.tgz"  The script is run unattended by a user that has been duly authorized through changes in the sudoers file. Everything runs smoothly except in this step: /usr/bin/sudo /bin/rm$DESTINAS$OLDTAR  The log file shows no errors but there's nothing in the place of the $OLDTAR variable, like it is not resolved, so it actually executes:

/usr/bin/sudo /bin/rm /Volumes/path-to-backup/


However if I run the commands in the terminal one by one I get it to work well. It may be a problem of user permissions?

• If, instead of executing the rm command, use echo $DESTINAS$OLDTAR what does it output? – Allan Oct 10 '16 at 17:06
• @Allan: it looks correct, it composes the full path and filename. – naio Oct 10 '16 at 17:26
• are there spaces? – Allan Oct 10 '16 at 17:44
• @Allan nope, it's filename_YYYY-MM-DD_HHMM.tgz – naio Oct 10 '16 at 18:13
• check to see if it exists using if [ -f $DESTINAS$OLDTAR ] then rm -f "$DESTITAR$NEWDIR.tgz" else echo "file not there" fi Add that conditional statement to your script – Allan Oct 10 '16 at 18:18

This is not a real answer, but I would pick apart your question into 4 smaller tasks.

1. Set up permissions / ACL so you don't need sudo if at all possible
2. Just set up a script to tar the files locally - and date stamp the backup
3. Set up a script to rsync the backup directory from the local server to the NAS. You can use the --delete option or --delete-after if you want to expire old backups over time.
4. Set up a script to purge dated backups in the local backup folder

Also - if you can't avoid using root /sudo - add this line tmutil snapshot before any delete and check one time to allow for local backups tmutil enablelocal in general so you have a backup if a script deletes too much. Time Machine will allow you recover rapidly from any errors in the logic of the scripts.

Lastly - for debugging bash - run bash -x script or set debugging set -x to see the values of the variables and see if you have a path error / encoding error or something else amiss.

• Thanks @bmike this is a complete remake of the script I may consider when I get more bash knowledge. Just one question: why do you recommend rsync rather than copy? it's only for the delete expired copies feature or for something else? – naio Oct 11 '16 at 10:44
• @naio I like that rsync has a --dry-run option to tell me what would be copied or deleted without doing the work. It handles large files - if the copy fails or gets interrupted, it picks up half way done with a file. It's fast, corrects errors and is really useful. You can use it like cp if you want easy - but it's quite powerful in ways cp is not. – bmike Oct 11 '16 at 18:11

I've found what was going on: the user executing the script had not sufficient permissions to read on the NAS directory, so the result of this:

OLDTAR=$(/bin/ls /Volumes/path-to-backup/ | head -n 1)  was an empty string, this is where the script failed. Instead If I do: OLDTAR=$(/usr/bin/sudo /bin/ls /Volumes/path-to-backup/ | head -n 1)


it works as I expected.