I need a command that manages automatically the naming of files for backup purposes. For example, I have a file called test.txt, and sometimes I manually need to update that file calling a bash script that "recalculates" test.txt.

I usually, before calling that bash script, I manually do a copy of the file with a format like:

cp test.txt test.txt.bk.x

where x is the number of the last backup + 1.

I would like to put a command at the beginning of my bash script like:

backup_cp -options_about_backup_filename_format test.txt

that manages automatically the naming of the next backup file. I don't need to obey the current file naming pattern, it could be any sequential format, for example like the log files in /var/log where the backup n. 1 is always the latest backup, or as the current one, where the backup numbers are in growing order.

It would be awesome if the command could also erase the oldests backups automatically.


Take a look at logrotate command. You specify with a config file how to backup older version. Then you would call:

logrotate -f config_file

An simple example of a config file would be:

/path/to/text.txt {
  rotate 10

You have many other options like: dateext, postrotate, prerotate, etc.

With dateext the date is added at the end of filename, so you know when the backup was created. Post/Pre rotate can execute some tasks before and after backup.

If you use number it is slightly different as you are used to. 1 is the last file and the age grows with number.

Do not put config file in /etc/logrotate.d/, because logrotate runs automatically config files from that directory. You want to run it only when you want, and supply the config file to logrotate.

  • Thanks, that is what daemons use to manage /var/log entries isn't? I was thinking on it but I didn't remember the name, and I thought it was design as a daemon, not as a command you can call occasionally. – Peregring-lk Oct 26 '17 at 14:59
  • Yes, that is what is used to rotate logs in /var/log. You can take a look into etc/logrotate.d/* files and see how it is done. – nobody Oct 27 '17 at 7:44

You could just generate a number and then keep upping it and logging it in a file.


ID=`cat $IDFILE`

#New ID for the next one
echo $[ID + 1] > $IDFILE

Create a .id_number file with the a number as it's content with which you want to start and you can start using it.


I've created a bash script that is able to handle similar task.

The script features

  • The script will crate a backup copy of the target file or directory. Also it can handle multiple files and (or) directories. The name of the new file (or the new directory) will be target.N, where N is the consecutive number of the backup copy.

  • The script's has two options:

    • --backup-chain=<chain name> - this option will append the string <chain name> to the name of the backup file and numbering of this chain will be independent from the other chains.

    • --verbose-mode - this option will append -v to the list of cp command options.

  • Few examples of usage are presented here: https://paste.ubuntu.com/25847541/


1. Create executable script file, called sbcp (simple backup copy), that is located in /usr/local/bin to be accessible as shell command:

sudo touch /usr/local/bin/sbcp
sudo chmod +x /usr/local/bin/sbcp
sudo nano /usr/local/bin/spcp

2. The content of the script sbcp is:


# simple backup copy - sbcp

# Compose the info message - ref: https://askubuntu.com/a/583445/566421
info_message() {
        printf "Please set target - one or more file or directory: \e[33msbcp 'file1' 'file2' 'dir1/file3' 'dir2'\e[0m\n"
        printf "Use the option \e[33m--backup-chain='chain name'\e[0m or \e[33m--backup-chain=chain_name\e[0m to create different backup chains.\n"
        printf "Use '\e[33msbcp *\e[0m' to make a backup copy for all items in the current directory, non recursively.\n"

# If the STDIN is not empty, then do the operations, else just output the info message
if [ ! -z "${@+x}" ]; then

        # Check whether there options are set - this should be more elegant
        for item in "$@"; do
                # Find the backup chain name
                if [[ "$item" =~ --backup-chain=.* ]]; then
                        BC="$(echo "${item}" | sed -e 's/--backup-chain=//' -e 's/\"//g' -e "s/'//g")"
                        [[ -z "$BC" ]] && BC="$BC" || BC=".$BC"
                # Check whether the option --backup-chain os set
                if [[ "$item" =~ --verbose-mode.* ]]; then cp_options="-pvir"; else cp_options="-pir"; fi

        # Check whether there are other input parameters different than the option --backup-chain, if there is not - output the info message and exit
        if [ "$(echo "$@" | sed -e 's/--backup-chain=/./' -e 's/\"//g' -e "s/'//g")" == "${BC}" ]; then info_message && exit 1; fi

        # Output the backup chain name
        [[ -z "$BC" ]] && echo "Backup chain: .N" || echo "Backup chain: ${BC}.N"

        # The main part - create backup copies
        for item in "$@"; do
                if [[ ! "$item" =~ --backup-chain=.* ]] && [[ ! "$item" =~ --verbose-mode.* ]]; then
                        LAST="$(ls -1d "${item}${BC}".* 2>/dev/null | awk -F'.' '{print $(NF)}' | grep -Po '[0-9]+' | sort | tail -n1)"
                        cp "$cp_options" "${item}" "${item}${BC}.$((LAST+1))"

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.