Skip to content
Joachim Ansorg edited this page Nov 12, 2021 · 7 revisions

Make sure not to read and write the same file in the same pipeline.

Problematic code:

grep foo file.txt | sed -e 's/foo/bar/g' > file.txt

Correct code:

grep foo file.txt  | sed -e 's/foo/bar/g' > tmpfile && mv tmpfile file.txt

Rationale:

Each step in a pipeline runs in parallel.

In this case, grep foo file.txt will immediately try to read file.txt while sed .. > file.txt will immediately try to truncate it.

This is a race condition, and results in the file being partially or (far more likely) entirely truncated.

Note that this can also be a problem when you write to a file and read from it later in the pipe. The second command (which reads the file) may not see all the output of the first. An exception in this case is a non-greedy file reader like less, for example python foo.py 2> errfile.txt | less - errfile.txt will successfully allow you to see stdout and stderr separately in less.

Exceptions

You can ignore this error if:

  • The file is a device or named pipe. These files don't truncate in the same way.
  • The command mentions the filename but doesn't read/write it, such as echo log.txt > log.txt.

Additional Resources

ShellCheck

Each individual ShellCheck warning has its own wiki page like SC1000. Use GitHub Wiki's "Pages" feature above to find a specific one, or see Checks.

Clone this wiki locally