Chapter 9. Files and More

What makes a plain old file a shell script, and how do you emit exit codes? How do you read files? We’ll talk about all that—and more—in this chapter.

Reading Files

There are three main idiomatic ways to read files into a bash script. Some of them “slurp” the entire file into memory, and others work one line at a time.

read

We’ve already used read for processing key/value pairs in Chapter 2, and we’ll see it again in “Getting User Input”, but the other major use is reading files and parsing input one line at a time:

$ grep '^nobody' /etc/passwd | read -d':' user shadow uid gid gecos home shell

$ echo "$user | $shadow | $uid | $gid | $gecos | $home | $shell"
 |  |  |  |  |  |

Wait, what happened? Where’s my data? Well, that’s a gotcha—it went into the subshell created by the pipe (|), and it never came out. What about this?

$ grep '^nobody' /etc/passwd | { \
    read -d':' user shadow uid gid gecos home shell; \
    echo "$user | $shadow | $uid | $gid | $gecos | $home | $shell" \
  }
nobody |  |  |  |  |  |

That’s slightly better, but where’s the rest of it? Well, -d is the end-of-line delimiter, not the field separator ($IFS). One more try:

$ grep '^nobody' /etc/passwd | { \
    read -d':' user shadow uid gid gecos home shell; \
    echo "$user | $shadow | $uid | $gid | $gecos | $home | $shell" \
  }
nobody | x | 65534 | 65534 | nobody | /nonexistent | /usr/sbin/nologin

See also “Fiddling with $IFS for Fun and Profit, to Read Files”.

lastpipe

If you are running bash 4+, you can set ...

Get bash Idioms now with the O’Reilly learning platform.

O’Reilly members experience live online training, plus books, videos, and digital content from nearly 200 publishers.