The standard redirect to file;
and piping output from one command to anotherls > /tmp/listing
But bourne-shell derivatives give you even more power than that.ls | wc -l
Most properly written programs output in one of two ways.
An uncommon program to use for this example is the "fuser" program under solaris. it gives you a long listing of what processes are using a particular file. For example:
If you wanted to see just the processes using that file, you might initially groan and wonder how best to parse it with awk or something. However, fuser actually splits up the data for you already. It puts the stuff you may not care about on stderr, and the meaty 'data' on stdout. So if you throw away stderr, with the '2>' special redirect, you get$ fuser /bin/sh /bin/sh: 13067tm 21262tm
which is then trivially usable.$ fuser /bin/sh 2>/dev/null 13067 21262
Unfortunately, not all programs are that straightforward :-) However, it is good to be aware of these things, and also of status returns. The 'grep' command actually returns a status based on whether it found a line. The status of the last command is stored in the '$?' variable. So if all you care about is, "is 'biggles' in /etc/hosts?" you can do the following:
As usual, there are lots of other ways to accomplish this task, even using the same 'grep' command. However, this method has the advantage that it does not waste OS cycles with a temp file, nor does it waste memory with a potentially very long variable.grep biggles /etc/hosts >/dev/null if [[ $? -eq 0 ]] ; then echo YES else echo NO fi
wc -l /etc/hosts wc -l < /etc/hosts cat /etc/hosts | wc -l
Additionally, if there are a some fixed lines you want to use, and you do not want to bother making a temporary file, you can pretend part of your script is a separate file!. This is done with the special '<<' redirect operator.
means, "run 'command', but make its stdin come from this file right here, until you see the string 'EOF'"command << EOF
EOF is the traditional string. But you can actually use any unique string you want. Additionally, you can use variable expansion in this section!
if you do NOT want to use variable expansion, then use "EOF" rather than EOF.DATE=`date` HOST=`uname -n` mailx -s 'long warning' root << EOF Something went horribly wrong with system $HOST at $DATE EOF
This is a fairly easy way to find what entries in /etc/hosts both match a particular pattern in their name, AND have a particular IP address ranage.grep hostspec /etc/hosts| awk '{print $1}' | fgrep '^10.1.' | wc -l
The "disadvantage" to this, is that it is very wasteful. Whenever you use more than one pipe at a time, you should wonder if there is a better way to do it. And indeed for this case, there most certainly IS a better way:
There is actually a way to do this with a single awk command. But this is not a lesson on how to use AWK!grep '^10\.1\..*hostspec' /etc/hosts | wc -l
But it is important to note that pipes by default only take the data on stdout! So it is possible to get an interactive view of the process, by usingtar cf - dirname | compress > file.tar.Z
stdout has been redirected to the pipe, but stderr is still being displayed to your terminal, so you will get a file-by-file progress report. Or of course, you could redirect it somewhere else, withtar cvf - dirname | compress > file.tar.Z
tar cvf - dirname 2>/tmp/tarfile.list | compress > file.tar.Z
Here's an example that doesnt do anything useful
wc will report that it saw two files, "/dev/fd/4", and "/dev/fd/5", and each "file" had 1 line each. From its own perspective, wc was called simply aswc -l <(echo one line) <(echo another line)
wc -l /dev/fd/4 /dev/fd/5
There are two useful components to this: