Skip to main content

Use the -n/-i flags to avoid overwriting files with cp and mv

The mv and cp builtins have a -n flag (no-clobber), and will prevent them from overwriting an existing file. They also have a -i flag (interactive)

I saw these flags mentioned in a Discord; I wanted to do a few experiments to see how they work in practice (and whether they’d be useful for me). I ran these tests with the macOS tools, but they may differ on other platforms.

cp

This will prevent overwriting files, and gives you a distinct exit code if it’s unable to copy the file.

Here’s an example:

echo "red triangle" > shape.txt
echo "blue circle" > new_shape.txt

cp -n new_shape.txt shape.txt
echo "$?"       # --> 1
cat shape.txt   # --> red triangle

cp new_shape.txt shape.txt
echo "$?"       # --> 0
cat shape.txt   # --> blue circle

If you use cp -i, it has similar behaviour, returning different exit codes depending on whether or not the filw as overwritten:

echo "red triangle" > shape.txt
echo "blue circle" > new_shape.txt

cp -i new_shape.txt shape.txt  # --> n
echo "$?"                      # --> 1
cat shape.txt                  # --> red triangle

cp -i new_shape.txt shape.txt  # --> y
echo "$?"                      # --> 0
cat shape.txt                  # --> blue circle

mv

This will prevent overwriting files, but it always has exit code 0, whether or not it moved the file.

Here’s an example:

echo "red triangle" > shape.txt
echo "blue circle" > new_shape.txt

mv -n new_shape.txt shape.txt
echo "$?"      # --> 0
ls             # --> new_shape.txt shape.txt

mv new_shape.txt shape.txt
echo "$?"      # --> 0
ls             # --> shape.txt

And the same exit codes if you overwrite a file (or not) with mv -i:

echo "red triangle" > shape.txt
echo "blue circle" > new_shape.txt

mv -i new_shape.txt shape.txt  # --> n
echo "$?"                      # --> 0
ls                             # --> new_shape.txt shape.txt

mv -i new_shape.txt shape.txt  # --> y
echo "$?"                      # --> 0
ls                             # --> shape.txt