To read a text file literally, don't use plain read
, which processes the output in two ways:
read
interprets \
as an escape character; use read -r
to turn this off.
read
splits into words on characters in $IFS
; set IFS
to an empty string to turn this off.
The usual idiom to process a text file line by line is
while IFS= read -r line; do …
For an explanation of this idiom, see Why is while IFS= read
used so often, instead of IFS=; while read..
?.
To write a string literally, don't just use plain echo
, which processes the string in two ways:
- On some shells,
echo
processes backslash escapes. (On bash, it depends whether the xpg_echo
option is set.)
- A few strings are treated as options, e.g.
-n
or -e
(the exact set depends on the shell).
A portable way of printing a string literally is with printf
. (There's no better way in bash, unless you know your input doesn't look like an option to echo
.) Use the first form to print the exact string, and the second form if you want to add a newline.
printf %s "$line"
printf '%s\n' "$line"
This is only suitable for processing text, because:
- Most shells will choke on null characters in the input.
- When you've read the last line, you have no way to know if there was a newline at the end or not. (Some older shells may have bigger trouble if the input doesn't end with a newline.)
You can't process binary data in the shell, but modern versions of utilities on most unices can cope with arbitrary data. To pass all input through to the output, use cat
. Going on a tangent, echo -n ''
is a complicated and non-portable way of doing nothing; echo -n
would be just as good (or not depending on the shell), and :
is simpler and fully portable.
: >| "$file"
cat >>"$file"
or, simpler,
cat >|"$file"
In a script, you usually don't need to use >|
since noclobber
is off by default.
> $file
. This only works as the first thing that looks for stdin in the parent shell script. Basically all of David's code can be reduced to a single character, but I think thecat -
is more elegant and less trouble prode because it's understood on sight. – Caleb Aug 19 '11 at 20:10cat
s together, just to annoy UUOC fanatics – Michael Mrozek Aug 19 '11 at 20:32cat
just so people who insist on using it necessarily have to do mental gymnastics to read the code. Named pipes are also good targets. – Caleb Aug 19 '11 at 20:37grep foo file
could be "Go look for bar in the third drawer of my file cabinet." andgrep foo < file
could be "Find the paper labeled bar in this stack of papers." The subject is an implied "you" with is left off since you are speaking to the shell. – Caleb Aug 22 '11 at 09:30command args < data
is inherently obtuse. – Caleb Aug 22 '11 at 16:05