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 ...

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

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.