Perl Help in the Unix Shell

I often work with lists of files in Unix. Usually those lists are generated with find. The other day, I had a list and I had deleted a lot of unwanted entries from the list, which I usually do on-the-fly in vim as I see things I don’t want to include, I’ll run a :g?/\.svn/?d, for example, to delete all files with /.svn/ in their path.

After a bit of work, I realized I had directories in the list, which I did not want. If I had had presence of mind to start with, I could have done something like find . ! -type d but I don’t want to start over and have to make all the edits again.

Perl to the rescue in the form of a one-liner!

Starting with this sample file ~/a.in:

.
./fruit
./fruit/apple.txt
./fruit/banana.txt
./jewels
./jewels/diamond.txt
./jewels/ruby.txt
./vegetables
./vegetables/carrots.txt

I run this:

$ perl -lne '-d || print' ~/a.in >~/a.out

Which gives me:

$ cat ~/a.out
./fruit/apple.txt
./fruit/banana.txt
./jewels/diamond.txt
./jewels/ruby.txt
./vegetables/carrots.txt

Arguments are as follows (see perl --help for more detailed information):
* l automatically chomp each line, removing the newline at the end of it
* n puts the code inside a while() { ... } loop
* e execute the next argument as code (which goes inside while loop)
* '-d || print' the current line is a directory OR (||) print it
* ~/a.in the input file which contains the names of files and directories
* >~/a.out send output to file ~/a.out

If you’re very confident, you can run:

$ perl -i -lne '-d || print' ~/a.in

The switch -i tells perl to edit the file in place. There are options to back up the original file if you’re less confident – see perl --help

Leave a comment