Unix is amazing. Only your imagination limits the usefulness of the built-in commands. You can create your own commands and then pipe them together, allowing one utility to work on the results of another. If you're like me, you've run across dozens of useful combinations over the years. Here are some of my favorite one-liners, intended to demonstrate useful ideas as well as to prime your pump for writing your own one-liner hacks. 9.12.1 Simultaneously Download and UntarHave you ever downloaded an extremely large archive over a slow connection? It seems to take forever to receive the archive and forever to untar it. Being impatient, I hate not knowing how many of the archived files are already here. I miss the ability to work on those files while the rest of the archive finishes its slow migration onto my system. This one-liner will decompress and untar the files as the archive downloads, without interfering with the download. Here's an example of downloading and untarring the ports collection: # tail -f -b=1m ports.tar.gz | tar -zxvf ports.tar.gz ports/ ports/Mk/ <snip> Here I've asked tail to stream up to one megabyte of the specified file as it is received. It will pipe those bytes to the tar utility, which I've directed to decompress (-z) and to extract (x) the specified file (f) while displaying the results verbosely (v). To use this command, download the archive to where you'd like to untar it in this example, /usr. Simply replace the filename ports.tar.gz with the name of your archive. 9.12.2 When Did I Change That File?Do you ever need to know the last modification date of a file? Consider a long listing: % ls -l filename -rw-r--r-- 1 dru wheel 12962 Dec 16 18:01 filename If you count the fields, the sixth (Dec), seventh (16), and eighth (18:01) fields all contain part of the modification date. However, there's whitespace separating those fields, which makes it difficult to determine their exact character positions. Fortunately, awk doesn't mind variable whitespace, so this one-liner will always work: % echo filename was last modified on `/bin/ls -l filename \ | awk '{print $6, $7, $8}'` filename was last modified on Dec 16 18:01 Here I've asked echo to repeat a string as well as the results of a command contained within single quotes. The first half of that command is simply ls -l filename. I've piped the output of that command to awk, which will print the sixth ($6), seventh ($7), and eighth ($8) fields of the long listing. Note that the awk action is enclosed between '{ }'. While this is a useful one-liner, it is fairly awkward to type as needed. However, if you replace filename with a positional parameter [Hack #13], you have a very handy script. I'll call mine when: % more ~/bin/when #!/bin/sh # script to list date of a file's last modification # replaces $1 with specified filename # or gives error message if user forgets to include filename if test $1 then echo $1 was last modified on `/bin/ls -l $1| awk '{print $6, $7, $8}'` else echo "Don't forget the name of the file you're interested in" exit 1 fi Once you've made your script executable, use when filename to find the date of a file's most recent modification. 9.12.3 Finding SymlinksIf you ever need to find symbolic links, you're in luck. find's -type l or link option serves just this purpose. Start with this invocation: % find /etc -type l -ls 25298 0 lrwxrwxrwx 1 root wheel 23 Apr 7 2003 /etc/termcap -> /usr/share/misc/termcap 25299 0 lrwxrwxrwx 1 root wheel 13 Apr 7 2003 /etc/rmt -> /usr/sbin/rmt 25301 0 lrwxrwxrwx 1 root wheel 12 Apr 7 2003 /etc/aliases -> mail/aliases 25305 0 lrwxr-xr-x 1 root wheel 36 Oct 26 09:08 /etc/localtime -> /usr/share/zoneinfo/America/Montreal Well, that worked, but the output is downright ugly. Let's pipe the results to our good friend awk to display only the last three fields. If you count them, those are fields 11 through 13: % find /etc -type l -ls | awk '{print $11, $12, $13}' /etc/termcap -> /usr/share/misc/termcap /etc/rmt -> /usr/sbin/rmt /etc/aliases -> mail/aliases /etc/localtime -> /usr/share/zoneinfo/America/Montreal Aah, much better. If you ever plan on needing to find symlinks, it's well worth saving this in a shell script similar to the when script shown previously. 9.12.4 Making cron More User-FriendlyAre you always forgetting the meanings of the various fields in a crontab? It would probably be a lot easier if your crontab began like this: # minute (0-59), # | hour (0-23), # | | day of the month (1-31), # | | | month of the year (1-12), # | | | | day of the week (0-6 with 0=Sunday). # | | | | | commands 3 2 * * 0,6 /some/command/to/run To achieve that, type those lines into a text file, say ~/cronheader. (Be patient, we're getting to the one-liner.) Then, open up your crontab editor: % crontab -e Unless you've changed your default editor, this will open up your crontab using vi. Place your cursor at the beginning of the file, and type the following: !!more /usr/home/dru/cronheader The !! tells vi to insert the output of the specified command. Be sure to give the full pathname to your file. vi will insert its contents for you once you press Enter. When you're finished, type :wq as usual to exit the editor. 9.12.5 See Also
|