Hack 99 Useful One-Liners


figs/beginner.gif figs/hack99.gif

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 Untar

Have 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 Symlinks

If 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-Friendly

Are 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

  • man tail

  • man tar

  • man cut

  • man awk



BSD Hacks
BSD Hacks
ISBN: 0596006799
EAN: 2147483647
Year: 2006
Pages: 160
Authors: Lavigne

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net