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.

3 min read

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 -d for temporary files, and pair them with trap ... EXIT for guaranteed cleanup even on error or interruption.
  • Prefer heredocs (<<EOF) over many chained echo >> 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 flock instead.

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. mktemp creates safe, unique temporary files/directories, and pairing it with trap ... EXIT guarantees 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 ... EXIT cleanup 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