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

# 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
    Commented Oct 10, 2016 at 17:06
  • @Allan: it looks correct, it composes the full path and filename.
    – naio
    Commented Oct 10, 2016 at 17:26
  • are there spaces?
    – Allan
    Commented Oct 10, 2016 at 17:44
  • @Allan nope, it's filename_YYYY-MM-DD_HHMM.tgz
    – naio
    Commented Oct 10, 2016 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
    Commented Oct 10, 2016 at 18:18

2 Answers 2


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
    Commented Oct 11, 2016 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
    Commented Oct 11, 2016 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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .