Skip to content
VLSI Mentor

Linux & Bash · Part I · Module 3 · Creating and Changing Files and Directories

Copying and Moving: cp, mv and What They Overwrite

Two commands, both of which look obvious and neither of which is. cp duplicates something; mv relocates or renames it. What makes them worth a careful chapter is that both decide what your command means by checking the filesystem first — the same words produce different results depending on whether the destination already exists — and that both will overwrite an existing file completely silently, returning success. This is the first point in the course where a correctly typed command with a correct exit status can leave you worse off than before you ran it, and the habits that prevent that are cheap to learn now.

Foundation18 min readLinuxPart IFundamentalsFilesData Safety

Part I · Module 3 · Chapter 3.2 · Copying and Moving

1. Two Jobs, One Shape

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cp  SOURCE  DESTINATION      duplicate it — the original stays
mv  SOURCE  DESTINATION      relocate or rename it — the original is gone

Both take at least two operands, and Chapter 1.5's rule about operand position applies with force: the last one is the destination, and the others are sources. Swap them and you have asked for something quite different.

Both are external programs, so — per Chapter 1.7 — their exact messages vary a little between systems. The behaviour taught here does not.

2. cp — The Simple Cases

Copy a file to a new name in the same directory:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project/rtl

$ ls
alu.sv  counter.sv

$ cp alu.sv alu_backup.sv

$ ls
alu.sv  alu_backup.sv  counter.sv

Two files now exist with the same contents. The original is untouched — that is the whole difference from mv.

Copy a file into a directory, keeping its name:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ cp rtl/alu.sv docs

$ ls docs
alu.sv

The destination docs is a directory that exists, so cp put the file inside it and kept the name. Copy several at once, and the last operand must be a directory:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp rtl/alu.sv rtl/counter.sv docs

$ ls docs
alu.sv  counter.sv

Every path form from Module 2 works in either position:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp ../rtl/alu.sv .                     # from a sibling, into here
$ cp /etc/os-release ~/notes/            # absolute source, home destination
$ cp alu.sv ../docs/alu_copy.sv          # up and across, with a new name

Note the second line: . and ~ are doing exactly what Chapter 2.3 said they do, and cp has no idea they were ever involved — the shell replaced ~ before cp started.

3. How cp Decides What You Meant

This is the rule behind every surprise in the chapter, so it is worth stating on its own:

cp looks at the destination. If it is an existing directory, the file goes inside it. Otherwise the destination is treated as a file name.

Both halves are reasonable. Together they create a trap:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ls
docs  rtl  scripts  sim

$ cp rtl/alu.sv backup

$ ls -l backup
-rw-r--r-- 1 engineer engineer 482 Mar 20 14:20 backup

There is no directory called backup, so cp did the second thing: it created a file called backup, containing a copy of alu.sv. Read the listing with Chapter 2.5 — the leading - confirms it is an ordinary file, not a directory.

Nothing failed. The exit status was zero. You asked for a file named backup and you got one.

4. Both Commands Overwrite Without Asking

Here is the behaviour this chapter exists for.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ printf 'the new work\n' > draft.txt
$ printf 'a week of edits\n' > report.txt

$ cat report.txt
a week of edits

$ cp draft.txt report.txt

$ echo $?
0

$ cat report.txt
the new work

The previous contents of report.txt are gone. Not in a recycle bin, not recoverable. cp printed nothing, asked nothing, and reported success — because from its point of view it succeeded completely.

mv behaves the same way:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ printf 'ONE\n' > m1.txt
$ printf 'TWO\n' > m2.txt

$ mv m1.txt m2.txt

$ cat m2.txt
ONE

$ ls m1.txt
ls: cannot access 'm1.txt': No such file or directory

Two files became one. m2.txt's contents were replaced, and m1.txt no longer exists because mv moved it.

The options that make it ask

Two options change that, and both are worth knowing:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -i draft.txt report.txt
cp: overwrite 'report.txt'? n

-i is interactive: ask before overwriting, and do nothing if you answer no.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -n draft.txt report.txt

$ cat report.txt
a week of edits

-n is no-clobber: never overwrite, and do not ask either. The existing file survived and the copy simply did not happen.

Both options exist for mv as well. -i suits you at a prompt; -n suits a command you want to be safe without a human present.

A third option is useful for a different reason:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -v rtl/alu.sv docs/
'rtl/alu.sv' -> 'docs/alu.sv'

-v is verbose: say what was done. It does not prevent anything, but it tells you the destination the command actually resolved — which is exactly the thing §3's trap gets wrong.

5. Copying a Directory Needs -r

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ cp rtl backup_rtl
cp: -r not specified; omitting directory 'rtl'

cp copies files. To copy a directory and everything inside it, ask for recursion:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -r rtl backup_rtl

$ ls backup_rtl
alu.sv  counter.sv

-r is for recursive: descend into the directory and copy what is found, all the way down. Chapter 1.5's rule holds — it is a short option, and cp -rv combines two.

6. The cp -r Destination Trap

Now the trap that catches people for years. The same command produces two different results depending on something you did not type.

Copying a directory with cp dash r has two different outcomes. When the destination does not exist, it is created as a copy of the source, so the files land directly inside it. When the destination already exists, the source directory is placed inside it, adding one extra level.Destination missingcp -r rtl backupWhat happensbackup is created as a copyof rtlYou getbackup/alu.svDestination existscp -r rtl backupWhat happensrtl is placed inside backupYou getbackup/rtl/alu.sv12
Figure 1 — one command line, two outcomes. Nothing in the typed text distinguishes these cases; the difference is whether the destination already existed when the command ran. Running the same command twice therefore produces a different arrangement the second time, which is how a nested copy appears without anyone asking for one.

In a session, destination missing:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ls
docs  rtl  scripts  sim

$ cp -r rtl backup

$ ls backup
alu.sv  counter.sv

backup did not exist, so it was created as a copy of rtl. The files sit directly inside it.

Now run the identical command again, with backup now present:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -r rtl backup

$ ls backup
alu.sv  counter.sv  rtl

$ ls backup/rtl
alu.sv  counter.sv

This time rtl was placed inside backup, adding a level nobody asked for. Both runs are cp applying §3's rule consistently: an existing directory destination means put it in here.

7. mv — Rename and Move Are the Same Thing

A point that saves confusion: Linux has no separate rename command, because renaming is moving.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project/rtl

$ mv counter.sv counter_8bit.sv

$ ls
alu.sv  counter_8bit.sv

The file stayed in the same directory and got a different name. Chapter 2.1 explained that a directory holds entries, and that a file's name lives in that entry. Changing the name and changing which directory holds the entry are the same operation on the same thing — so one command does both.

Moving into another directory:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ mv notes.txt docs/

$ ls docs
notes.txt

Moving and renaming at once:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ mv rtl/alu.sv docs/alu_reference.sv

Several files into one directory, with the destination last:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ mv a.txt b.txt c.txt docs/

mv follows exactly the same destination rule as cp: an existing directory means into it; anything else is a name. And it needs no -r for directories, because moving a directory does not involve copying what is inside it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ mv sim/run1 sim/run1_old

8. The Failures Worth Recognising

Overwriting something you wanted — §4. The fix is a habit, not an option: look before you write.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ls -l report.txt
-rw-r--r-- 1 engineer engineer 8192 Mar 19 09:30 report.txt

If that command prints a line, the destination exists and your copy will replace it. If it prints No such file or directory, you are creating something new. One command, complete certainty.

The file named after a directory you thought existed — §3. cp x.txt backup with no backup directory gives you a file called backup. Use the trailing slash.

Copying a directory without -r — §5. This one is safe: it refuses and tells you.

A typo in the destination:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ mv report.txt docs/reprot.txt

Nothing failed. You now have a correctly moved file with a misspelled name, and ls docs is how you find out. -v would have shown it immediately.

Copying a directory and losing its hidden files. Chapter 2.6 warned that patterns beginning with * skip names starting with a dot. A copy written with a pattern can silently leave configuration behind:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -r project/* backup/        # dotfiles in project/ are NOT copied

Copying the directory itself, rather than a pattern of its contents, avoids the problem entirely:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -r project backup_project   # everything, including hidden entries

Why the pattern misses them is Chapter 3.5's subject, and the full rule is Module 9's.

9. Why This Matters in Engineering Work

Two situations, no semiconductor knowledge needed.

Keep a copy before you edit something you did not write. Before changing a configuration or a script that other people depend on:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ cp -v setup.sh setup.sh.bak
'setup.sh' -> 'setup.sh.bak'

Two seconds, and the original is recoverable. This is the cheapest insurance available on a system with no undo, and it is the habit most often skipped by people who later wish they had it.

Never copy onto a results directory. Output directories are the classic place for §6's trap to do damage: copy new results onto an existing directory and you get a mixture of two runs with no record of which file came from where. Chapter 3.1's one-directory-per-run convention exists partly to make this impossible — a fresh directory cannot be a stale one.

Part II returns to both habits where results and reproducibility are the whole subject.

10. Practice

The starting tree:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
/home/engineer/project
├── docs
│   └── readme.md
├── rtl
│   ├── alu.sv
│   └── counter.sv
└── sim

Your working directory is /home/engineer/project for every question.

Question 1. cp rtl/alu.sv docs — where does the file land, and what is it called? Which fact about docs decided that?

Question 2. cp rtl/alu.sv archive — there is no archive. What exactly exists afterwards, and how would ls -l archive prove it?

Question 3. Rewrite the command in Question 2 so that it fails loudly instead of producing the wrong thing.

Question 4. cp docs/readme.md rtl/alu.sv runs and prints nothing. What has happened to alu.sv? What would you have run first to know in advance?

Question 5. cp -r rtl sim — sim exists. Give the full path of the copied alu.sv. Now suppose sim had not existed: give the path in that case.

Question 6. You want to rename sim to sim_old. Write the command, and say why no -r is needed even though it is a directory.

Question 7. mv rtl/counter.sv rtl/conuter.sv succeeds. What went wrong, why did nothing report it, and which option would have shown you?

Question 8. Moving a large directory takes a second one day and twenty minutes the next, with the same command. Give the likely reason, using a term from Chapter 2.1.

11. Remember

  • cp duplicates and leaves the original. mv relocates, and the original is gone. The last operand is always the destination.
  • Both decide the destination's meaning by looking at it. An existing directory means inside it; anything else is treated as a file name.
  • A missing destination directory becomes a file of that name. The trailing slash — backup/ — says you meant a directory, and turns the mistake into an error.
  • Both overwrite an existing file silently and report success. There is no confirmation and no undo. -i asks first, -n refuses to overwrite, -v says what was actually done.
  • cp needs -r for a directory and refuses safely without it. mv never needs it.
  • cp -r src dest has two outcomes: if dest is missing it becomes a copy of src; if it exists, src is nested inside it. Running the same command twice therefore gives different results.
  • Rename and move are one operation, because a name is just an entry in a directory.
  • ls -l on the destination before you write to it is the whole safety practice, and it costs one command.
  • A pattern like project/* skips hidden entries. Copy the directory itself when you mean everything.

Both commands in this chapter can destroy a file. The next one does nothing else — and unlike these two, it has no gentler mode to fall back on.

Where this fits

Part of the Linux & Bash curriculum.