Hi, My name is Sean Lum. I've run into something on my Linux systems (Debian, Fedora, and Arch, occurring both in bash and sh on all three, and all the machines are up to date at the time of testing), and it involves shell input/output redirects and the cat command. I am not completely sure on how the cat command handles shell redirects, but similar behavior is also present in the less command. I am unsure if this is a bash command or cat command issue or a less command issue.
The issue is as such, when the input file is the output file, in a truncating redirect, the file is truncated, and no content written to the file by the redirect. This behavior is the same on the less command, using the ">" operator, but has differing behavior on the ">>" operator. $ echo "hi" > file.txt $ cat file.txt hi $ cat file.txt > file.txt $ cat file.txt <no output> $ echo "hi" > file.txt $ cat file.txt >| file.txt <no output> $ echo "hi" > file.txt $ echo $(cat file.txt) > file.txt $ cat file.txt <no output> $ cat file.txt >> file.txt cat: file.txt: input file is output file In bash(1) under Redirecting Output. I notice that: "If the file does not exist it is created; if it does exist it is truncated to zero size." ... "If the redirection operator is >, and the noclobber option to the set builtin has been enabled, the redirection will fail if the file whose name results from the expansion of word exists and is a regular file. If the redirection operator is >|, or the redirection operator is > and the noclobber option to the set builtin command is not enabled, the redirection is attempted even if the file named by word exists." My question is, even with the noclobber operator set, why is the content of the file truncated and not overwritten with the same file content if the input file is also an output file? Similar behavior occurs in the less command as well (file truncated with ">", file contents appended after file contents with ">>"). I'm still confused, is this defined or undefined behavior? Is there an explanation for this? My thoughts on possibilities: 1. I am not understanding the way bash works with the cat command, and this is expected behavior. 2. Fencing issues with memory access, the input file and output file are the same, and a file descriptor related error arises? Or a read/write error arises? 3. A race condition in the order of processing in the bash script causing the file to be truncated after the file contents are written? 4. Could be something else, I haven't quite gotten to the point of inspecting source code yet. Thank you, and I hope you have a great day, - Sean Lum
