Guide
Bash-Scripting
Intermediate
File Handling
Reading, writing, appending, checking, and looping over files in Bash — the everyday file-manipulation patterns used in real scripts.
Checking Files Before Using Them
FILE="config.yaml"
if [ -f "$FILE" ]; then
echo "Exists and is a regular file"
fi
[ -d "/var/log" ] && echo "Directory exists"
[ -r "$FILE" ] && echo "Readable"
[ -w "$FILE" ] && echo "Writable"
[ -s "$FILE" ] && echo "Exists and is non-empty"
Writing to Files
echo "line 1" > output.txt # overwrite (creates the file if missing)
echo "line 2" >> output.txt # append
cat <<EOF > config.yaml # heredoc: write a multi-line block cleanly
environment: production
region: us-east-1
debug: false
EOF
cat <<'EOF' > script.sh # single-quoted EOF disables variable expansion inside
echo "This \$VAR is printed literally"
EOF
Reading Files
cat file.txt # dump entire content
CONTENT=$(cat file.txt) # capture entire content into a variable
while IFS= read -r LINE; do # the correct, safe way to process line by line
echo "Line: $LINE"
done < file.txt
head -n 10 file.txt # first 10 lines
tail -n 10 file.txt # last 10 lines
tail -f app.log # follow a growing file live
Copying, Moving, Deleting
cp source.txt dest.txt
cp -r source_dir/ dest_dir/
mv old_name.txt new_name.txt
rm -f temp_file.txt # -f suppresses "file not found" errors — useful in cleanup scripts
Creating Temporary Files Safely
TMPFILE=$(mktemp) # unique, safe temp file — avoids race conditions
echo "temp data" > "$TMPFILE"
# ... use it ...
rm -f "$TMPFILE"
TMPDIR=$(mktemp -d) # unique temp directory
trap 'rm -rf "$TMPDIR"' EXIT # always clean up, even if the script errors out
Never hardcode a “unique” temp filename like /tmp/myapp_$$ — while better than a fixed name, mktemp is the actual safe, race-condition-free way to get one.
Checking If a File Was Modified Recently
find /var/log -name "*.log" -mtime -1 # modified in the last 1 day
find /var/log -name "*.log" -mmin -30 # modified in the last 30 minutes
if [ "app.log" -nt "app.log.bak" ]; then # -nt = "newer than"
echo "app.log is newer than the backup"
fi
Locking a File to Prevent Concurrent Script Runs
LOCKFILE="/tmp/deploy.lock"
if [ -e "$LOCKFILE" ]; then
echo "Another deploy is already running" >&2
exit 1
fi
touch "$LOCKFILE"
trap 'rm -f "$LOCKFILE"' EXIT
# ... deploy logic here ...
Working With Paths
FULL_PATH="/var/log/nginx/access.log"
basename "$FULL_PATH" # "access.log"
dirname "$FULL_PATH" # "/var/log/nginx"
realpath "../config.yaml" # resolve to an absolute path
FILE="report.tar.gz"
echo "${FILE%%.*}" # "report" — strip everything from first dot
echo "${FILE##*.}" # "gz" — extension only (last dot)
Production Considerations
- Always use
mktemp/mktemp -dfor temporary files, and pair them withtrap ... EXITfor guaranteed cleanup even on error or interruption. - Prefer heredocs (
<<EOF) over many chainedecho >>lines when writing multi-line config files — cleaner and less error-prone. - Simple lock files (as shown) work for single-host scripts, but aren’t atomic under race conditions — for anything more critical, use
flockinstead.
Quick Interview Answer
“File tests (
-f,-d,-r,-s) guard against operating on missing or wrong-type files before acting.>overwrites,>>appends, and heredocs (<<EOF) cleanly write multi-line content.mktempcreates safe, unique temporary files/directories, and pairing it withtrap ... EXITguarantees cleanup runs even if the script exits early due to an error.”
Common Mistakes
- Using
>when>>was intended, silently truncating a file that was meant to be appended to. - Hardcoding a “unique” temp filename instead of using
mktemp, risking a race condition if the script runs concurrently. - Forgetting
trap ... EXITcleanup for temp files/lock files, leaving stale artifacts after a script errors out mid-run.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form