I am trying to create a routine to manage the backup files I am creating, so that older folders will be deleted automatically in the process. Here’s what I've got:

day=$(date +%m%d%y)
oldday=$(date -d "-4 days" +%m%d%y)
mkdir /home/fauna/backup/$day
rm -r /home/fauna/backup/$oldday
cp /home/fauna/backup/backup.sh /home/fauna/backup/$day
cd /home/fauna/backup/$day

backup.sh actually does the creation of the backup files and then copies the folder with those files to a remote location.

Will that rm line delete that old folder without any unintended consequences?

Can I move it to after the backup.sh line?

  • 1
    You may want to create the new backup file before you delete the old one. You know, so that you have a backup.... – Wildcard Mar 17 '16 at 8:51

Adding a check is a good idea:

if [[ -d ~/backup/$oldday ]]; then
  rm -rf "$HOME/backup/$oldday"

Also, using single or double quotes correctly in bash is important. Especially directory names with spaces in them can cause problems when not using quoting.

Update: I am assuming OP wants to use bash.

  • Doesn't the comment about quotes also apply to the part that comes between the [[ and ]]? – RealSkeptic Mar 17 '16 at 8:47
  • 1
    @RealSkeptic, no, it doesn't. – Wildcard Mar 17 '16 at 8:49
  • The OP never mentioned bash. [[...]] is ksh syntax (also supported by zsh and bash), not sh. – Stéphane Chazelas Mar 17 '16 at 9:11
  • 1
    @Wildcard It doesn't in this case, but you might want to get into the habit of using double quotes anyway, because in [[ $a == $b ]] the lack of double quotes around $b does make a difference. I added a note to this effect in that answer. – Gilles Mar 17 '16 at 22:39

You've got a few issues with coding practice in your code.

  1. You'd want to check for the success of those commands especially when the next command depends on the success of the previous one.
  2. Leaving a variable unquoted in list context is asking the shell to split it and perform filename generation on it, there's no reason you'd want to do that here.

Now about rm -r, it's mean to delete the directory and all its content. It will not follow symlinks when doing so. Even if /home/fauna/backup/$oldday is a symlink, only that symlink is removed. That's probably what you want here. It would be different if you did rm -r "/home/fauna/backup/$oldday/" (with the trailing /).

However, without -f, that that means that if stdin is a terminal, you could be prompted for the removal of non-writable files. So, if it's meant to be an unattended script, you should probably add it. Also with -f, rm only reports failure if the directory if still there afterwards.

#!/bin/sh -
day=$(date +%m%d%y) || exit
oldday=$(date -d "-4 days" +%m%d%y) || exit
# date is very unlikely to fail, but if it does, it would have dramatic consequences

# shouldn't access to those directories be restricted (if it hasn't been
# restricted already some levels above)?
# umask 077

mkdir -p "/home/fauna/backup/$day" || exit
# with -p, mkdir would only fail if the directory is not there after that call.
# It may not be what you want though. You may want mkdir to fail if the
# directory already existed in which case you'd want to omit the -p.

cp /home/fauna/backup/backup.sh "/home/fauna/backup/$day" || exit

cd "/home/fauna/backup/$day" || exit
./backup.sh || exit

# only delete the old one if the new one succeeds.
rm -rf "/home/fauna/backup/$oldday"

Note that here since we're adding || exit to every command, we might as well use set -e which causes the shell to exit upon any error of any command, but I prefer || exit as it makes it explicit that you've given consideration into error handling (and set -e has too many gotchas to be used reliably (not in this simple case here though)).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.