Linux Basics: Prevent Accidental Output Overwrites with noclobber
A plain > can replace an existing report before the command produces any useful output. Bash’s noclobber option makes that redirection fail for an existing regular file. Practice checking the refusal, making a deliberate exception, and limiting the option to one part of a script.
These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh. Each script creates a different named text file in the fresh scratch directory. Run each once before cleanup. Its first protected write refuses an existing practice file rather than reusing it.
Prepare a scratch directory
You need Bash, a text editor, and the cat, mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file in this directory before running it. The guards stop setup if it fails; invoking bash explicitly avoids changing executable permissions. No administrator access is needed.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 11. Refuse an accidental replacement
Save this as clobber-protect.sh:
#!/usr/bin/env bash
set -o noclobber
printf 'original report\n' > clobber-protected.txt || exit 1
if { printf 'replacement\n' > clobber-protected.txt; } 2>/dev/null; then
printf 'Unexpected overwrite\n'
exit 1
else
printf 'Existing file kept\n'
fi
IFS= read -r saved < clobber-protected.txt || exit 1
printf 'Content: %s\n' "$saved"Run it:
bash clobber-protect.shOutput:
Existing file kept
Content: original reportThe first write creates a new file. The second redirection fails before its printf runs, and the conditional handles that failure. Reading the file afterward confirms that the original line remains.
The enclosing brace group redirects Bash’s expected error message to /dev/null so the example can print a stable explanation. Keep diagnostics visible in normal troubleshooting. If a write fails unexpectedly, distinguish overwrite protection from permission errors, a missing parent directory, or a full filesystem rather than assuming every failure has the same cause.
2. Replace once deliberately, then append
Save this as clobber-override.sh:
#!/usr/bin/env bash
set -C
printf 'draft\n' > clobber-override.txt || exit 1
printf 'reviewed\n' >| clobber-override.txt || exit 1
printf 'approved\n' >> clobber-override.txt || exit 1
printf 'After replacement and append:\n'
cat -- clobber-override.txtRun it:
bash clobber-override.shOutput:
After replacement and append:
reviewed
approvedset -C is the short form of enabling noclobber. The >| operator makes one explicit overwrite exception, so draft is replaced by reviewed. Appending with >> still works while the option is enabled, adding approved without discarding the preceding line.
Use the exception only after choosing the destination deliberately. It does not bypass filesystem permissions, guarantee that the producing command succeeds, or make the replacement transactional. A failed producer may still leave an empty or partial file after an allowed redirection.
3. Limit protection to a subshell
Save this as clobber-scope.sh:
#!/usr/bin/env bash
set +C
(
set -C
printf 'inside\n' > clobber-scope.txt || exit 1
if { printf 'refused\n' > clobber-scope.txt; } 2>/dev/null; then
exit 1
else
printf 'Subshell: overwrite blocked\n'
fi
) || exit 1
printf 'outside\n' > clobber-scope.txt || exit 1
printf 'After returning to the outer shell: '
cat -- clobber-scope.txtRun it:
bash clobber-scope.shOutput:
Subshell: overwrite blocked
After returning to the outer shell: outsideThe outer script explicitly starts with protection disabled. The parenthesized section enables it locally and confirms that a repeated write is blocked. When that section finishes, the outer shell can overwrite the file using plain > because its own option was never changed.
A script can use this pattern around a small export operation without changing later writes. The standalone script does not change the launching terminal’s settings either. Do not assume an option enabled in one shell is active in every other process that may write the same file.
Keep in mind
This option guards particular shell output redirections, not all filesystem changes. It does not stop an editor, cp, or a program that opens files itself. It is not a backup, a general file lock, or a complete defense against hostile pathname changes. Keep important outputs backed up and choose a proper atomic-write strategy when partial results would be harmful.
Clean up
In the same terminal, remove only the named practice files, return to your original directory, and remove the empty scratch directory:
rm -- clobber-protected.txt clobber-override.txt clobber-scope.txt
rm -- clobber-protect.sh clobber-override.sh clobber-scope.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirReferences
Acknowledgements
This post was created with assistance from AI.