Classic Shell Scripting - Arnold Robbins [21]
* * *
Special files: /dev/null and /dev/tty
Unix systems provide two special files that are particularly useful in shell programming. The first file, /dev/null, is often known as the "bit bucket." Data sent to this file is thrown away by the system. In other words, a program writing data to this file always believes that it has successfully written the data, but in practice, nothing is done with it. This is useful when you need a command's exit status (described in Section 6.2) but not its output. For example, to test if a file contains a pattern:
if grep pattern myfile > /dev/null
then
... Pattern is there
else
... Pattern is not there
fi
In contrast to writes, reading from /dev/null always returns end-of-file immediately. Reading from /dev/null is rare in shell programming, but it's important to know how the file behaves.
The other special file is /dev/tty. When a program opens this file, Unix automatically redirects it to the real terminal (physical console or serial port, or pseudoterminal for network and windowed logins) associated with the program. This is particularly useful for reading input that must come from a human, such as a password. It is also useful, although less so, for generating error messages:
printf "Enter new password: " Prompt for input
stty -echo Turn off echoing of typed characters
read pass < /dev/tty Read password
printf "Enter again: " Prompt again
read pass2 < /dev/tty Read again for verification
stty echo Don't forget to turn echoing back on
...
The stty (set tty) command controls various settings of your terminal (or window).[7] The -echo option turns off the automatic printing (echoing) of every character you type; stty echo restores it.
Basic Command Searching
Earlier, we mentioned that the shell searches for commands along the search path, $PATH. This is a colon-separated list of directories in which commands are found. Commands may be compiled executables or shell scripts; there's no real distinction from the user's perspective.
The default path varies from system to system. It will contain at least /bin and /usr/bin. It might contain /usr/X11R6/bin for X Windows programs, and it might also contain /usr/local/bin for programs that your local system administrator has installed. For example:
$ echo $PATH
/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin
The term "bin" for directories that hold executables is short for binary. However, you can also think of it as having the corresponding English meaning—a place to hold things; in this case, executable programs.
When you write your own scripts, it would be nice to have your own bin in which to place them, and have the shell find them automatically. This is easy to do. Just create your own bin directory and add it to the list in $PATH:
$ cd
Change to home directory
$ mkdir bin
Make a personal "bin" directory
$ mv nusers bin
Put our script there
$ PATH=$PATH:$HOME/bin
Append our bin directory to PATH
$ nusers
Test it out
6 The shell finds it
To make the change permanent, add your bin directory to $PATH in your .profile file, which is read every time you log in, by putting a line like this at the end of it:
PATH=$PATH:$HOME/bin
Empty components in $PATH mean "the current directory." An empty component can be designated by two successive colons in the middle of the path value, or by a leading or trailing colon, which puts the current directory first or last, respectively, in the path search:
PATH=:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin Current directory first
PATH=/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin: Current directory last
PATH=/bin:/usr/bin:/usr/X11R6/bin::/usr/local/bin Current directory in middle
If you wish to include the current directory in the search path, it is preferable to use an explicit dot in $PATH; this makes it clearer to the reader of your program what's going on.
In our testing, we found two versions of the same system that did not correctly support supplying an empty component at the end of $PATH.