HAL: Part 3 Functions
I began this series with HAL: Part 1 Preliminaries. I followed this with HAL: Part 2 My Favourite Aliases. This article deals with functions and another will talk about scripts.
In the first article there was a link which would allow the reader to download my HAL. There you will find 63 functions. My use of aliases predates my use of functions, so I would expect fewer functions to be obsolete.
And yet, as I went through my functions while writing this article, I found several that I no longer use; didn't realise I had.
Note that sometimes you will notice a function (for example, 'help'), and another with the same name with 'o' at the end ('helpo'). This is my convention for the older version of a function. It allows me to be experimental in modifying a function, confident that I can easily invoke the previous version which worked well.
In writing this article, I learned a trick. To list all aliases, one simply issues the command alias without arguments. How do I list bash functions? In the past I have used set, but that lists all variables as well as functions. Eventually I discovered the less-than-obvious declare -f.
* * * * * * * * * * * * * BSD_su HP_su Linux_su
The su command must be about the most idiosyncratic command found on Unix-like platforms. In ~/.bashrc, I define functions for each platform. Near the bottom of that file, I set the alias su according to the current platform.
On a FreeBSD machine, I see this:
type -a su su is aliased to `BSD_su' su is /usr/bin/su
whereas on a Linux machine I see this:
type -a su su is aliased to `Linux_su' su is /bin/su
* * * * * * * * * * * * * alias
The alias function was discussed in part 2. It's probably worth repeating.
Normally, you have to write
alias name=value
My function allows me to write
alias name value
This is why in $HOME/.ENV./.cshrc_bash you will see all the aliases defined without the use of an equal sign (=).
I started using c-shell before I discovered bash (which originated about 1989). In c-shell, the syntax for aliases does not use an equal sign:
alias name wordlist
My function facilitated the transition from c-shell to bash.
* * * * * * * * * * * * * cutf
For many requirements, cut is much more flexible than awk. Syntax like -f 3-7, imbues cut with a convenience which is vastly greater than that of awk. However, cut is much more restrictive in its notion of a field; whereas awk understands fields in a more human way. If a delimiter is not specified to awk, it treats white space as a delimiter. The default delimiter for cut is the tab character.
I think I intended to build up my function cutf over time. In the event, it has served me well in its initial incarnation.
I can (and often do) write something like
scan | grep -i article | cutf 1
in preference to
scan | grep -i article | awk '{print $1}'
It's just so much more convenient.
Here's why I might do it. This example is from the way I handle my mail with nmh. I've edited a little for readability.
$ scan | grep -i article 30 -14Feb2011 Ben Okopnik Re: Article (perhaps): Life Can be Tough 33 14Feb2011 Ben Okopnik Re: Article update: Everything You Always 52 19Feb2011 Ben Okopnik Re: Rounding articles $ aaa=`scan | grep -i article | cutf 1` $ refile $aaa +lg
The first command displays a summary of current emails (in my inbox), 1 line per email, for those lines in which the string "article" appears. In the second command, I gather together just the first field of each line (the message numbers). The third command moves the selected messages to a different mailbox.
I could do the above in fewer lines, but that's not my objective here.
* * * * * * * * * * * * * dc
This function panders to my apparent dyslexic typing. I often get the order of my characters wrong. I may type dc $HOME when I meant to type cd $HOME. There is a command dc (an arbitrary precision calculator), but the way I use it, it normally takes no arguments. The dc function checks if there is a single argument, and whether that single argument is a directory, and if so does what I meant rather than what I said. If I type dc without args, it invokes the command dc.
Obviously, I never use the first form deliberately.
* * * * * * * * * * * * * dirs dsd dsdc dth files links
These are all variations on the ls command. dirs shows just directories; files shows just regular files; links shows just symbolic links. dsd shows all entries except for emacs backup files with the result piped through more.
dsdc is like dsd but only shows entries with today's (the current) date. It turned out to be a stepping stone. I think something like dsdc existed on VMS. Nothing similar was available on Linux. However, these days dth has almost completely supplanted dsdc.
The function dth was discussed exhaustively in What Really Matters or The Counting Article.
* * * * * * * * * * * * * gt_doit gttv gttvu gtx
In essence, gttv is a function which lists the table of contents of a tar-zipped file. It performs gunzip or bunzip2 (depending on file type) piped into "tar -tvf -" piped into my pager. gttvu does all of the above preceded by a uudecode (not all that common these days). gtx is like gttv except it unpacks a tar-zipped file.
gt_doit is simply the helper function invoked by the other functions.
* * * * * * * * * * * * * help
This function is discussed in detail in Henry's Techno-Musings: My Help System.
* * * * * * * * * * * * * lesh
One of my most frequently used functions. Think of it as a cross between less and dth. With no arguments, it works like less on the most recent file in the current directory. If the first argument is of the form +n, it displays the first n files in the current directory, or, if there are args after the +n, the first n files which match the remaining args. If args are files, they are the candidates for most recent; if they are directories, the files within those directories are the candidates.
For example, lesh +3 /var/log will display the 3 most recent files in the system log directory.
The section "My 'less' command" in Henry's Techno-Musings: My Help System explains why this allows me to scan through several files conveniently.
* * * * * * * * * * * * * lest
I really should use the concept of this function more extensively. Let's say I have script. It could be mine, or one somewhere on the system; I know its name; it's in my path; but I can't remember where it is. Or I can remember where it is, but I don't really care. I just want to look at it with less. lest scriptname will find it and open it. For example, irb is a ruby script in /usr/local/bin. lest irb opens it in less.
It's a consolidation of my typical behaviour. Often, I found myself going type -a command, then wanting to look in the file in the answer.
Here's a better example. It shows that lest also works on aliases.
type -a tcu tcu is aliased to `/home/henryg/scripts/tarcompressuuencode.sh'
less tcu makes no sense ("tcu: No such file or directory"). But lest tcu works just fine.
* * * * * * * * * * * * * loc
This is my variation on find. With a single arg, it looks in the current directory tree for an entry with the supplied string somewhere in its name. With 2 args, it takes the first as the directory to search.
These days I think it would be more useful if it were rewritten to do "find | grep" rather than "find -name".
* * * * * * * * * * * * * mangl
Sometimes I get the impression there are man pages everywhere. It's hard to keep up. On most of the systems I manage, I have a pretty good handle on where man pages are. But even on these systems, some man pages pop up in unexpected places. On systems that I visit but don't control, man pages could be anywhere. If I've tried apropos and man and still haven't found what I'm looking for, I might try locate. If this exposes a man page of interest, I can use mangl pathname to get the man page formatted with nroff.
And, yes, the name is a weak pun.
* * * * * * * * * * * * * mcd
Another simple function that often gets a work-out. Basically, mkdir plus cd: make a directory and cd to it.
* * * * * * * * * * * * * ping
I have never seen the point of having ping relentlessly bang on the door of the remote machine. It reminds me of Sheldon in The Big Bang Theory: [knock, knock, knock] "Penny!" [knock, knock, knock] "Penny!" [knock, knock, knock] "Penny!"
/sbin/ping fw PING fw (192.168.0.1): 56 data bytes 64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=0.340 ms 64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.278 ms 64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=0.207 ms 64 bytes from 192.168.0.1: icmp_seq=3 ttl=64 time=0.240 ms ...
Surely once is enough:
ping fw PING fw (192.168.0.1): 56 data bytes 64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=0.277 ms--- fw ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.277/0.277/0.277/0.000 ms
On Solaris, by default, all you get is a single line: "fw is alive".
* * * * * * * * * * * * * truss
A very important function. I guess I encountered truss on Solaris. I learned to use and love it. So, of course, when I moved to other platforms, I soon felt the need. Linux flavours have strace; FreeBSD has truss, but the parameters are different.
Once again, I have a function that hides these idiosyncrasies from me and lets me get on with the job.
And That's About It
I don't think there's much more to say about functions. Only 14 descriptions of about 25 functions. The others aren't worth the trouble.
Share |
Talkback: Discuss this article with The Answer Gang
Henry has spent his days working with computers, mostly for computer manufacturers or software developers. His early computer experience includes relics such as punch cards, paper tape and mag tape. It is his darkest secret that he has been paid to do the sorts of things he would have paid money to be allowed to do. Just don't tell any of his employers.
He has used Linux as his personal home desktop since the family got its first PC in 1996. Back then, when the family shared the one PC, it was a dual-boot Windows/Slackware setup. Now that each member has his/her own computer, Henry somehow survives in a purely Linux world.
He lives in a suburb of Melbourne, Australia.