[Chapter 9] 9.24 Get File List by Editing Output of ls -l, grep, etc.
Author: Jerry Peek, Tim O'Reilly & Mike Loukides
Date: 1998-08-04T21:35:31Z

#

| Chapter 9 Saving Time on the Command Line |

## 9.24 Get File List by Editing Output of ls -l, grep, etc.

It seems like I'm always using ls-also, usually, -l and maybe other options - to find out which of my files I need to do something to. I also use grep or one of the other greps (27.1) to search for files that have certain text in them. No matter what command I use, I redirect the output (13.1) to a temporary file (21.2, 21.3) and then edit the file. After the editing, I have a list of filenames that I can use inside backquotes (9.16) with some other command - or store in a shell variable (6.8).

Here are two examples. These show the vi editor, but you can use any other UNIX editor that handles plain text files. Depending on what you need, there are probably UNIX utilities that can help.

### 9.24.1 What Files Have I Just Edited?

While I was working on this book, my current directory could have around 1000 files. If I wanted to find out which files I'd edited today, I would use ls -lt (16.2) to get a listing of files with the most recently modified listed first. Edit the file, delete all lines except files I'd edited today, then remove everything from each line except the filename. Finally, use backquotes and rcp (1.33) to copy the files to the ptbackup directory on the fserver computer:

1. Make the file list and start the editor:

       !$
       % ls -lt > /tmp/bk$$
       % vi !$
       vi /tmp/bk28182

2. Delete all lines except the ones for files from February 29:

   >     total 4294                                           << delete
   >     -rw-r--r--  1 jerry        1529 Feb 29 17:25 a7630
   >     -rw-r--r--  1 jerry        1864 Feb 29 16:29 a0147
   >        ...Keep these lines...
   >     -rw-r--r--  1 jerry        1772 Feb 29 09:01 a1900
   >     -rw-r--r--  1 jerry        2693 Feb 29 08:51 a0031
   >     -rw-r--r--  1 jerry         744 Feb 28 23:35 a7600   << delete
   >     -rw-r--r--  1 jerry        1957 Feb 28 22:18 a5210   << delete
   >        ...Delete the rest...

3. In vi, use the `|` (vertical bar) command (30.34) to find the column number just before the filenames start. For example, here's where the commands `30|`, `39|`, and `45|` moved the cursor:

   >     -rw-r--r--  1 jerry        1529 Feb 29 17:25 a7630
   >                                30^      39^   45^

4. So, I want to delete columns 1-45 from every line. The easiest way is a filter-through (30.22) with colrm 1 45 (35.15) or cut -c46- (35.14):

   >     :%!cut -c46-

5. Now the file looks like this - just the filenames:

   >     a7630
   >     a0147
   >     ...
   >     a1900
   >     a0031

   I can sort it with `:%!sort` if I want to - or do more editing. Then I write the file and quit.

6. Feed the list of filenames to the UNIX command I want to run:

   >     % rcp `cat /tmp/bk$$` fserver:ptbackup

   This works with most any UNIX command - not just rcp. For example, if I want to print the files, I can use:

   >     % lpr `cat /tmp/bk$$`

7. If I'll be doing a lot of work with the filenames, typing the backquotes over and over is a pain. I'll store the filenames in a shell variable (6.8):

   - First, pick a name for the shell variable. I usually choose temp because it's not used on my account. You should check the name you choose before you set it by typing `echo` `"$``varname``"`; be sure it's empty or useless.

   - Store the filenames from your temporary file:

     >     % set temp=(`cat /tmp/bk$$`) ...C shells
     >     $ temp="`cat /tmp/bk$$`" ...Bourne shells

   - Use the shell variable. For example:

     >     % cp $temp backupdir
     >     % vi $temp
     >     % ...

(Sometimes, find with operators like -newer (17.8) is easier - but find searches subdirectories too, unless you use -prune (17.23).) Oh, try to remember to rm the temp file when you're done with it.

### 9.24.2 Search for Text with grep

The grep -l option (15.7) gives you a list of filenames that match a string - that might be all I need. But sometimes I need to see the lines that grep found to decide whether to include that file or not. Here's how:

1. Search the files. Be sure that your grep-like command will print the filename before each matching line:

   >     % egrep -i "summar(y|ies)" * > /tmp/bk$$

2. Edit the temporary file. The lines will look something like this:

   >     a0066:Here is a summary of the different components:
   >     a0183:Summary: String functions in awk
   >     a0183:for a summary of all the string functions
   >     a0184:Let's start wlth a short summary how awk treats command
   >     a1000:Here's a summary of the rules that UNIX uses to interpret paths:
   >     a1000:Here's a summary of the different sorts of wildcards available:
   >     a1680:cumulative summary files and ASCII reports in
   >     a2710:In summary, \fIcomm\fP is similar to \fIdiff\fP:
   >        ...

   Leave a line for each file that you want to operate on; delete the rest:

   >     a0066:Here is a summary of the different components:
   >     a0183:Summary: String functions in awk
   >     a1000:Here's a summary of the different sorts of wildcards available:
   >        ...

3. Strip off everything after the filenames. Unless any of your filenames have colons (`:`) in them, you can tell vi to strip off the colons and everything after them. That command is:

   >     :%s/:.*//

   If there's a chance that a filename might be repeated (because grep matched more than one line), filter the filenames through sort -u to get rid of duplicates. In vi, type:

   >     :%!sort -u

   Like before, what's left is a list of filenames:

   >     a0066
   >     a0183
   >     a1000
   >         ...

   You can feed them to whatever command you need to run, as in the previous example.

I hope those two examples give you the idea, which is: learn what UNIX utilities are "out there"-and how to grab and edit their output to do what you want.

- JP

9.23 Workaround for "Arguments too long" Error |  | 9.25 The C Shell repeat Command