Creating, Copying, Moving, and Removing Files
File operations are among the most common and most destructive Linux tasks. This lesson develops a controlled workflow: identify exact paths, preview the operation, choose explicit command behavior, verify the result, and preserve a recovery path.
Learning objectives
By the end of this lesson
- Create directories and files with explicit, predictable paths.
- Copy files and directory trees while choosing overwrite and metadata behavior deliberately.
- Move and rename filesystem objects without losing track of source and destination semantics.
- Remove files and directories with safeguards appropriate to interactive and automated work.
- Apply preview, verification, and rollback habits to a realistic release-workspace lab.
1. A filesystem operation has a target and a consequence
Commands such as cp, mv, and
rm look simple, but their effect depends on pathname
resolution, whether a destination exists, shell expansion,
permissions, filesystem boundaries, and command options. Reliable
operators make those conditions visible before changing state.
flowchart TD I["Identify source and destination"] --> P["Print working directory and preview paths"] P --> C["Choose explicit command options"] C --> E["Execute one bounded operation"] E --> V["Verify names, type, size, and content"] V --> R["Retain backup or rollback path"]
Wildcards and variables may be expanded by the shell before
cp, mv, or rm starts.
Always reason about the final argument list, not merely the text
you typed.
2. Create directories and files deliberately
mkdir creates directories. Without -p, it
fails when a required parent is missing or when the target already
exists. With -p, it creates missing parents and treats
an existing directory as success.
workspace="$HOME/devops-academy/linux/chapter04/lesson01"
mkdir -p -- "$workspace"/{source,staging,archive}
# Create a file with known content rather than an ambiguous empty placeholder.
printf '%s\n' 'service_name=demo-api' 'port=8080' > "$workspace/source/app.conf"
# Create an empty marker only when emptiness is the intended state.
touch -- "$workspace/source/.initialized"
printf 'Created workspace:\n'
find "$workspace" -maxdepth 2 -printf '%y %p\n' | sort
The separator -- ends option parsing for commands that
support it. A filename beginning with - is then treated
as an operand rather than an option. Quoting variables preserves
spaces and prevents unintended splitting and glob expansion.
mkdir dirCreate one directoryFails if the parent is absent or the target already
exists
mkdir -p pathCreate a directory hierarchyUseful for idempotent setup, but still fails if a path
component is a non-directory
touch fileCreate an empty file or update timestampsDoes not populate meaningful content
printf ... > fileCreate or replace a text fileTruncates an existing file before writing
3. Copy with explicit overwrite and metadata intent
cp SOURCE DESTINATION copies file data. When the
destination names an existing directory, the source basename is
placed inside that directory. When the destination is a
non-directory pathname, it becomes the new name. This distinction is
a common source of mistakes.
cd -- "$workspace"
# Copy one file to a new pathname. -v reports the operation.
cp -v -- source/app.conf staging/app.conf
# Refuse to overwrite an existing file.
cp -vn -- source/app.conf staging/app.conf
# Preserve mode, ownership when permitted, timestamps, and links for a tree.
cp -a -- source/. staging/source-snapshot/
# Compare copied content.
cmp -- source/app.conf staging/app.conf && printf 'content matches\n'
-n
No clobber
Do not overwrite an existing destination. Useful for cautious interactive copying, though scripts should still verify the result.
-i
Interactive prompt
Ask before overwrite. Appropriate for a human session, but unsuitable for unattended automation.
-a
Archive mode
Recursively copy a tree while preserving as much structure and metadata as practical.
-v
Verbose evidence
Print source and destination names so an operator can review what occurred.
For deployment automation, never depend on a shell alias such as
cp='cp -i'. Scripts run in different environments.
State every required option in the script and validate the
destination independently.
4. Move and rename: same command, different mechanics
mv renames or relocates filesystem entries. Within one
filesystem, a move is often a metadata operation: the directory
entry changes while file data remains in place. Across filesystems,
the implementation generally copies data and then removes the source
after a successful copy.
cd -- "$workspace"
# Rename within one directory.
mv -v -- staging/app.conf staging/app.conf.candidate
# Move into an existing directory.
mv -v -- staging/app.conf.candidate archive/
# Refuse to overwrite an existing destination.
mv -vn -- source/app.conf archive/app.conf
# Verify the final locations.
find source staging archive -maxdepth 2 -printf '%y %p\n' | sort
A same-filesystem rename can be atomic from the viewpoint of other processes, which makes it useful for publishing completed files. A cross-filesystem move cannot provide the same simple guarantee because data must be copied.
5. Removal unlinks names; it does not provide a recycle bin
rm removes directory entries. A normal command-line
environment does not move them to a graphical trash folder. Recovery
may be difficult or impossible, especially after storage blocks are
reused. The safest removal is one whose exact target set was already
printed and reviewed.
rm -- fileFile or symbolic linkFails for directories unless recursive mode is requested
rm -i -- fileInteractive file removalPrompts before each target; human-only safeguard
rmdir -- dirEmpty directoryRefuses to remove a non-empty directory
rm -r -- dirDirectory treeRecursive and potentially destructive; preview first
rm -rf -- dirTree without promptsForceful automation tool, not a default troubleshooting
response
target="$workspace/staging/source-snapshot"
# Preview the exact tree first.
printf 'Candidate removal tree:\n'
find "$target" -depth -printf '%y %p\n'
# Require the expected parent path before removal.
case "$target" in
"$HOME/devops-academy/linux/chapter04/lesson01/staging/"*)
rm -r -- "$target"
;;
*)
printf 'Refusing unexpected target: %s\n' "$target" >&2
exit 64
;;
esac
# Remove an empty directory with the narrower command.
rmdir -- "$workspace/staging"
6. Safer patterns for interactive and automated work
Run pwd -P and list the parent directory. Verify
that variables are non-empty and point below an expected root.
Use printf '%q\n', find, or a
command’s dry-run facility before a bulk change.
Operate on an explicit directory or array rather than an unreviewed wildcard from an unknown location.
Use no-clobber behavior, versioned backups, snapshots, or a staging directory when overwrites are possible.
Check existence, type, size, checksum, or content after the operation. A zero exit code is necessary but may not prove the intended result.
7. Hands-on lab: assemble and publish a release directory
This lab creates a miniature release workspace, builds a candidate directory, verifies it, publishes it through a rename, and removes only a disposable build area.
set -u
root="$HOME/devops-academy/linux/chapter04/lesson01-release"
source_dir="$root/source"
build_dir="$root/build/release-1.0.0"
releases_dir="$root/releases"
mkdir -p -- "$source_dir" "$build_dir" "$releases_dir"
printf '%s\n' '<h1>DevOps Academy demo</h1>' > "$source_dir/index.html"
printf '%s\n' 'version=1.0.0' > "$source_dir/release.env"
cp -a -- "$source_dir/." "$build_dir/"
printf '%s %s\n' \
"$(sha256sum "$build_dir/index.html" | awk '{print $1}')" \
'index.html' > "$build_dir/SHA256SUMS"
# Verify required files before publication.
for required in index.html release.env SHA256SUMS; do
test -f "$build_dir/$required" || {
printf 'missing required file: %s\n' "$required" >&2
exit 1
}
done
published="$releases_dir/1.0.0"
test ! -e "$published" || {
printf 'release already exists: %s\n' "$published" >&2
exit 1
}
mv -- "$build_dir" "$published"
printf 'Published release:\n'
find "$published" -maxdepth 1 -type f -printf '%f\n' | sort
# Remove only the now-empty build parent.
rmdir -- "$root/build"
printf 'Workspace retained at %s\n' "$root"
Verification checklist
8. Common file-operation mistakes
Assuming the destination meaning
cp source target behaves differently when
target is an existing directory. Inspect it before
running the command.
Using sudo to bypass ownership problems
This can create root-owned files inside a user workspace. Diagnose identity and permissions instead.
Trusting aliases as safeguards
Aliases may not exist in scripts, CI jobs, containers, or another operator’s shell.
Combining wildcard expansion with recursive force
The shell may produce a larger or different target set than expected. Preview expanded names and constrain the parent directory.
9. Knowledge check
Question 1. What does
cp source destination do when the destination is an
existing directory?
Question 2. Why can a same-filesystem
mv be safer for publishing a completed file than
copying directly into place?
Question 3. Why is rm -rf not an
appropriate default response to a removal problem?
10. Summary
Controlled file operations begin with explicit paths and end with
verification. mkdir and printf create
structure and content; cp duplicates data;
mv renames or relocates entries; rm and
rmdir unlink names. No-clobber options, bounded
targets, staging directories, and rollback paths turn fragile
commands into operational procedures.
11. Further reading
- GNU Coreutils manuals for mkdir, touch, cp, mv, rm, rmdir, install, and sha256sum.
- Linux manual pages for rename, unlink, open, stat, and path_resolution.
- POSIX specifications for cp, mv, rm, mkdir, and pathname handling.
- Filesystem Hierarchy Standard — placement and purpose of system directories.
- GNU Bash Reference Manual — quoting, expansion, exit status, and command execution.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.