Get the highlights in your inbox every week.
Two great uses for the cp command: Bash shortcuts
Two great uses for the cp command: Bash shortcuts
Here's how to streamline the backup and synchronize functions of the cp command.

Last July, I wrote about two great uses for the cp command: making a backup of a file, and synchronizing a secondary copy of a folder.
Having discovered these great utilities, I find that they are more verbose than necessary, so I created shortcuts to them in my Bash shell startup script. I thought I’d share these shortcuts in case they are useful to others or could offer inspiration to Bash users who haven’t quite taken on aliases or shell functions.
Updating a second copy of a folder – Bash alias
The general pattern for updating a second copy of a folder with cp
is:
cp -r -u -v SOURCE-FOLDER DESTINATION-DIRECTORY
where the -r
stands for “recursively descend through the folder visiting all files”, -u
stands for “update the target” and -v
stands for “verbose mode”, SOURCE-FOLDER
is the name of the folder that contains the most up-to-date information, and DESTINATION-DIRECTORY
is the directory containing copy of the SOURCE-FOLDER
that must be synchronized.
I can easily remember the -r
option because I use it often when copying folders around. I can probably, with some more effort, remember -v
, and with even more effort, -u
(is it “update” or “synchronize” or…).
Or I can just use the alias capability in Bash to convert the cp
command and options to something more memorable, like this:
alias sync='cp -r -u -v'
If I save this in my .bash_aliases
file in my home directory and then start a new terminal session, I can use the alias, for example:
sync Pictures /media/me/4388-E5FE
to synchronize my Pictures folder in my home directory with the version of the same in my USB drive.
Not sure if you already have a sync
alias defined? You can list all your currently defined aliases by typing the word alias
at the command prompt in your terminal window.
Like this so much you just want to start using it right away? Open a terminal window and type:
echo "alias sync='cp -r -u -v'" >> ~/.bash_aliases
Then start up a new terminal window and type the word alias
at the command prompt. You should see something like this:
me@mymachine~$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias gvm='sdk'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias sync='cp -r -u -v'
me@mymachine:~$
There you can see the sync
alias defined.
Making versioned backups – Bash function
The general pattern for making a backup of a file with cp
is:
cp --force --backup=numbered WORKING-FILE BACKED-UP-FILE
where the -- force
stands for “make the copy no matter what”, the -- backup=numbered
stands for “use a number to indicate the generation of backup”, WORKING-FILE
is the current file we wish to preserve, and BACKED-UP-FILE
is the same name as the WORKING-FILE
and will have the generation information appended.
Besides remembering the options to the cp
command, we also need to remember to repeat the WORKING-FILE
name a second time. But why repeat ourselves when a Bash function can take care of that overhead for us, like this:
Again, you can save this to your .bash_aliases
file in your home directory.
function backup {
if [ $# -ne 1 ]; then
echo "Usage: $0 filename"
elif [ -f $1 ] ; then
echo "cp --force --backup=numbered $1 $1"
cp --force --backup=numbered $1 $1
else
echo "$0: $1 is not a file"
fi
}
I called this function “backup” because I don’t have any other commands called “backup” on my system, but you can choose whatever name suits.
The first if
statement checks to make sure that only one argument is provided to the function, otherwise printing the correct usage with the echo
command.
The elif
statement checks to make sure the argument provided is a file, and if so, it (verbosely) uses the second echo
to print the cp
command to be used and then executes it.
If the single argument is not a file, the third echo
prints an error message to that effect.
In my home directory, if I execute the backup
command so defined on the file checkCounts.sql
, I see that backup
creates a file called checkCounts.sql.~1~
. If I execute it once more, I see a new file checkCounts.sql.~2~
.
Success! As planned, I can go on editing checkCounts.sql
, but if I take a snapshot of it every so often with backup, I can return to the most recent snapshot should I run into trouble.
At some point, it’s better to start using git
for version control, but backup
as defined above is a nice cheap tool when you need to create snapshots but you’re not ready for git
.
Conclusion
In my last article, I promised you that repetitive tasks can often be easily streamlined through the use of shell scripts, shell functions, and shell aliases.
Here I’ve shown concrete examples of the use of shell aliases and shell functions to streamline the synchronize and backup functionality of the cp
command. If you’d like to learn more about this, check out the two articles cited above: How to save keystrokes at the command line with alias and Shell scripting: An introduction to the shift method and custom functions, written by my colleagues Greg and Seth, respectively.
8 Comments, Register or Log in to post a comment.
I think that "sync" is not a good name for alias - sync (/bin/sync) is a program to synchronize data on disk with memory.
Thanks for the coment, Artur, good point! I had called this a number of other things along the way. Probably should change this too.
I think you should also consider using 'cp -av'. This preserves things like timestamps, which I often use when looking for some file I made some time ago, and when it was made helps me find it. 'cp -ruv' will make a copy with a brand-new timestamp.
An excellent idea, Greg!
Thanks for this writeup! I had no idea that 'cp' was capable of this. GUIs often keep me a bit removed from the terminal. Also, I find it easier to simply work with a graphical file manager.
These examples (among a few others I've collected since transitioning to Linux) are great reasons to open up the terminal!
I'm curious about Greg Pittman's contribution, re: timestamps. He seems to make a good point and if so... perhaps an article edit to address this(?).
Thanks for your comment, john379. Always nice to hear when people find something useful.
I like Greg's idea. Next time I revisit this article I will definitely add it!
If you find yourself with very similar or identical file names, use brace expansion https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html
cp --force --backup 1 my-file{,}
Lots of handy use cases, like for renames
mv foo.{txt,csv}
I
Thanks for your comment, tatethurston.
I love that use of the braces! I gotta say I spent many years using the c-shell in SunOS and Solaris and that one never occurred to me.