Expanding Your Toolkit: Using Saved Lists at the Linux $ Prompt
Expanding Your Toolkit is an occasional series which helps us integrate the MV and non-MV aspects of our jobs.
While I spend a majority of my working life in Multivalue — Unidata, specifically — I spend a good amount of time working in other environments as well. One of my favorite features of MultiValue that I miss in other environments is saved lists. I can't tell you how many times I've been working in a Linux shell and thought, "if only I had a saved list of items, this would be so much easier."
I recently needed to verify the compile dates on a list of items in a very cluttered program file. If only I had a saved list of the programs in Linux! With a saved list I could get my list, list the file and check the compilation dates on the items. But we can't do saved lists at the $ prompt in Linux. Or can we?
Spoiler alert: We CAN. Okay, so maybe it's not saved lists in the traditional MultiValue syntax, but we can do the same kind of thing quite easily.
Recently I needed to list the compile date of approximately 20 programs in a directory. To do this, I created a file in /tmp called list and cut-and-pasted the program names into this file, one program name per line. With this file in place, I used cd to get into the directory and then issued this command:
cat /tmp/list | xargs ls -l
The xargs command means "expand arguments." For each line in the /tmp/list file , xargs will add the file names after the ls -l up to the globbing limit , that is, the maximum length of a single shell command. If Linux runs out of space for the command before it runs out of names to add to the command, it'll reissue ls -l followed by the file names, again and again, until the list of names has been fully consumed.
This is just one way to use the xargs command. A little time with the xargs man page can reveal a number of other useful nuggets.
While this was useful, what I really needed was the compilation dates on the items, not the last update date on the source. And being just a little bit lazy, I really didn't want to have to go back and add an underscore in front of each item I had pasted into the /tmp/list_file (Unidata stores compiled code in the program file with an underscore in front of the name).
So rather than use xargs , I decided to use a for-loop instead. In my opinion, the for-loop is one of the most powerful shell scripting tools available, made even stronger by the fact that you don't need to create a shell script to use it. It works just as well from the command line.
The basic syntax of the for-loop looks like this the code:
for variable in `command` ; do
shell commands using $variable
Simply replace the variable with some letter or word and then use that variable between the do and done. That's it. For my particular dilemma — finding object code for the list of source items in /tmp/list — the command was as simple as:
for i in `cat /tmp/list` ; do
ls -l _$i
And yes, this is entered directly at the $ prompt! Here's how it works:
The backtick (`) operator runs a command. For each entry (variable i) in the result set, the scripting commands between the do and done are executed. The value of each entry in the result set (i) can be retrieved as a standard environment variable using $i. In this case, the loop expands to:
ls -l _item_1
ls -l _item_2
ls -l _item_3
ls -l item_n
The net result is that any list of items in a text record can be used as a saved list either through xargs or using a for-loop. Just because we're at the $ prompt shouldn't limit us from some of our MultiValue goodness.