If you try to modify a file (removing all empty lines for example) using a command like:
cat file.txt | sed '/^$/d' > file.txt
you will end up with and empty file.txt. The reason is that bash parses the command line looking for “metacharacters” ( “|” , “>” and “space” in this case) that separate words, then groups and executes those words according to their precedence. This means that “> file.txt” get executed FIRST. This creates an empty file.txt (overwriting any existing file) and a “process” to redirect standard output to that file. Then “cat file.txt” get executed, but by now file.txt is empty. So “cat file.txt” outputs 0 lines, “sed ‘/^$/d’ ” deletes all 0 empty lines, and 0 lines get written to file.txt . This works as “intended” and bash outputs no error.
You can get around this using a temporal file.
cat file.txt | sed '/^$/d' > tmp_file.txt mv tmp_file.txt file.txt
But, as file.txt is technically a new file you might lose some information, in particular permissions and whether file.txt was originally a symbolic link or not.
Other options is to use sponge, which is part of moreutils and sadly not standard in many systems.
cat file.txt | sed '/^$/d' | sponge file.txt