# Safe File Handling — Bash / Shell Scripting

Source: https://www.skillbyai.com/en/bash/s-files

> Handle awkward file names, write files atomically and prevent concurrent runs.

## Files are full of surprises

File names can contain spaces, newlines, leading dashes and glob characters, so treat them carefully: always quote expansions; use `--` to end options before file arguments (`rm -- "$file"` stops a file named `-rf` being read as options); use `find ... -print0 | xargs -0` or `find -exec ... {} +`; and loop with globs rather than parsing `ls` output. Write files **atomically**: write to a temporary file in the **same directory**, then `mv` it over the target, because a rename within one file system is atomic, so readers see either the old or the new file, never a half-written one. Prevent **concurrent runs** of a cron job with **`flock`**: `flock -n /run/lock/backup.lock cmd` exits immediately if another run holds the lock. Check free space before large writes, set a restrictive **`umask`** (such as 077) when creating files with secrets, and never store passwords in scripts; read them from environment variables or a secret manager.

## Atomic writes and single-instance locking

Readers never see a partial file, and two runs never overlap.

```bash
#!/usr/bin/env bash
set -euo pipefail

exec 9> /run/lock/export-prices.lock
flock -n 9 || { echo "another export is running" >&2; exit 0; }

target=/var/www/data/prices.json
tmp=$(mktemp "${target}.XXXXXX")       # same directory as the target

if curl -fsS "$PRICES_API" | jq '.' > "$tmp"; then
    chmod 644 "$tmp"
    mv -f -- "$tmp" "$target"           # atomic replace on the same file system
else
    rm -f -- "$tmp"
    echo "export failed; previous file left in place" >&2
    exit 1
fi
```

## Swapping a shop sign

You do not repaint the sign above the shop letter by letter while customers watch. You paint a new sign in the back room and swap it in one move. Atomic writes do the same for files.

**Quiz:** Why write to a temporary file in the same directory and then mv it over the target?

- [ ] mv compresses the file
- [ ] It avoids needing permissions
- [ ] Temporary files are faster to read
- [x] A rename within one file system is atomic, so readers never see a partially written file

*Answer:* A rename within one file system is atomic, so readers never see a partially written file. Atomic rename guarantees readers see either the complete old or complete new file.
