Bash Noclobber and Pipefail Edge Cases
Bash noclobber and pipefail edge cases are the honest limits of two safety settings. Noclobber blocks one kind of overwrite, and pipefail changes which pipeline stage decides success.
Noclobber refuses an overwrite
Noclobber is on and the file already exists. The second write is refused, the error names the file, and the old content survives.
set -o noclobber
printf 'old\n' > data.txt
printf 'new\n' > data.txt
cat data.txtDeliberate overwrite and append still work
Noclobber is on. The >| form replaces the file on purpose, and >> appends one more line, so the file ends with two lines.
set -o noclobber
printf 'old\n' > data.txt
printf 'new\n' >| data.txt
printf 'more\n' >> data.txt
cat data.txtPipefail exposes an early failed stage
Pipefail is on. The pipeline status is 1 even though the last stage succeeded, and PIPESTATUS shows the first stage failed while the second passed.
set -o pipefail
false | true
echo "status: $?"
false | true
echo "stages: ${PIPESTATUS[0]} ${PIPESTATUS[1]}"Example
set -o noclobber
set -o pipefail
printf 'first\n' > log.txt
printf 'second\n' >| log.txt
if false | true; then
echo "pipeline ok"
else
echo "pipeline failed"
fi
cat log.txt
echo "done"Key points
- Noclobber: set -o noclobber makes > refuse to overwrite an existing file.
- Noclobber limit: noclobber blocks > only, and >> still appends to an existing file.
- Override: >| overwrites even with noclobber on, so use it only on purpose.
- Pipefail: set -o pipefail makes a pipeline fail if any stage fails, not just the last.
- PIPESTATUS: PIPESTATUS holds one status per stage, in pipeline order.
- Errexit trap: with set -e, a pipefail pipeline failure exits the script unless guarded.
- Guard: an if test or || true around a pipeline keeps a known failure from killing the script.
In this example, noclobber and pipefail are both switched on. The log file is replaced on purpose with >|, so it holds the second line. The guarded pipeline reports its early failure instead of killing the script, and the final line proves the script survived.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
With set -o pipefail, what does false | true return?