Little big man

RELATED TOPICS

Unix Insider –

My series on "small fry" Unix commands did, I admit, overlook perhaps the smallest and also the most used command of them all.

The humble ls command is known by most users as ls, or ls -l. Some even know ls -F, but the ls command is much more powerful than these few options. This simple command provides several versions of listing functionality, at least a few of which you'll surely want to add to your arsenal after you've read this month's column.

The basic ls command will list the contents of a directory in alphabetical order and in four columns (usually), as in the following listing:

<font face="Courier">romany|mjb $ ls
PERSONALITY      copyxp           listen.tar       smit.log
Personly.dat     dwksave          lamage.cpio.Z    smit.script
Power.dt         ezcomp           log.txt          src.224
STARTUP          eztree           mbox             trash
acutime.cbl      fax              mftime.cbl       wisperr.log
alpha_port       holdit.c         mjb.grodin       xerox
amerc            junk.txt         necesito
bin              justio.c         open9ktrack.log
contest.txt      listen           setdwks
</font>

So far so good, but this command overlooks a few files that should be on the list. By default, any file that starts with a period (.) is not displayed. To get these files to display, use the -a option. A command-line option that is preceded by a dash (-) is often called a switch. The following is the output of ls -a:

<font face="Courier">romany|mjb $ ls -a
.                acutime.cbl      holdit.c         necesito
..               alpha_port       junk.txt         open9ktrack.log
.exrc            amerc            justio.c         setdwks
.profile         bin              listen           smit.log
.profile.031996  contest.txt      listen.tar       smit.script
.sh_history      copyxp           lamage.cpio.Z    src.224
PERSONALITY      dwksave          log.txt          trash
Personly.dat     ezcomp           mbox             wisperr.log
Power.dt         eztree           mftime.cbl       xerox
STARTUP          fax              mjb.grodin
romany|mjb $
</font>

This listing includes the dot (.) and double-dot (..) entries, representative of the current directory and the parent directory, which are part of any directory, as well as four new files that begin with a period.

The dot (.) and double-dot (..) entries are rarely wanted in a directory listing. They can be eliminated by using the ls -A option, which does the same job as ls -a, but skips the dot and double-dot entries, as in the following listing:

<font face="Courier">romany|mjb $ ls -A
.exrc            amerc            justio.c         setdwks
.profile         bin              listen           smit.log
.profile.031996  contest.txt      listen.tar       smit.script
.sh_history      copyxp           lamage.cpio.Z    src.224
PERSONALITY      dwksave          log.txt          trash
Personly.dat     ezcomp           mbox             wisperr.log
Power.dt         eztree           mftime.cbl       xerox
STARTUP          fax              mjb.grodin
acutime.cbl      holdit.c         necesito
alpha_port       junk.txt         open9ktrack.log
romany|mjb $
</font>

But what are these entries? Are these directories, files, or what? Command ls -l will give you the answers you seek, but it will also fill the screen with information you may not need.

Instead, use the -F option. This switch appends quick, identifying abbreviations to the end of each entry name to help you identify entries.

An executable file or program has an asterisk (*) appended to the entry name; a directory takes a slash (/), and a link to another file takes an at sign (@). The output of ls -F follows:

<font face="Courier">romany|mjb $ ls -F
PERSONALITY       copyxp/           listen.tar        smit.log
Personly.dat      dwksave/          lamage.cpio.Z     smit.script
Power.dt          ezcomp/           log.txt           src.224/
STARTUP*          eztree/           mbox              trash/
acutime.cbl       fax/              mftime.cbl        wisperr.log
alpha_port@       holdit.c          mjb.grodin/       xerox/
amerc/            junk.txt          necesito/
bin/              justio.c          open9ktrack.log
contest.txt*      listen/           setdwks
romany|mjb $
</font>

Combining -A and -F

Things are looking better, but now we've lost the files preceded by a period. To get them back again, we combine the -A and -F flags. In the listing below, the asterisk flag (*) indicates that .profile, .profile.031996, STARTUP, and contest.txt are executable files. The alpha_port entry is a link to some other entry. The entries terminated with a slash (/) are directories.

<font face="Courier">romany|mjb $ ls -AF
.exrc             amerc/            justio.c          setdwks
.profile*         bin/              listen/           smit.log
.profile.031996*  contest.txt*      listen.tar        smit.script
.sh_history       copyxp/           lamage.cpio.Z     src.224/
PERSONALITY       dwksave/          log.txt           trash/
Personly.dat      ezcomp/           mbox              wisperr.log
Power.dt          eztree/           mftime.cbl        xerox/
STARTUP*          fax/              mjb.grodin/
acutime.cbl       holdit.c          necesito/
alpha_port@       junk.txt          open9ktrack.log
romany|mjb $
</font>

If the output is to a terminal, the ls command lists files in multiple columns. If the output is piped to some other program, the multiple columns disappear and the output is formatted into a single column. Try piping all the work we've done so far through

<font face="Courier">more</font>
and a different picture emerges, as you see in the following two screens of output for ls -AF|more:

<font face="Courier">romany|mjb $ ls -AF|more
.exrc
.profile*
.profile.031996*
.sh_history
PERSONALITY
Personly.dat
Power.dt
STARTUP*
acutime.cbl
alpha_port@
amerc/
bin/
contest.txt*
copyxp/
dwksave/
ezcomp/
eztree/
fax/
holdit.c  
junk.txt
justio.c  
listen/
listen.tar
--More--

dwksave/
ezcomp/
eztree/
fax/
holdit.c  
junk.txt
justio.c  
listen/
listen.tar
lamage.cpio.Z
log.txt
mbox
mftime.cbl
mjb.grodin/
necesito/
open9ktrack.log
setdwks
smit.log
smit.script
src.224/
trash/
wisperr.log
xerox/
romany|mjb $
</font>

The -C flag

You can use the -C flag to force the output into multiple-column format, regardless of whether output is to a terminal or not. In the following listing, the output lists in four columns even though it's piped through more.

<font face="Courier">romany|mjb $ ls -AFC|more
.exrc             amerc/            justio.c          setdwks
.profile*         bin/              listen/           smit.log
.profile.031996*  contest.txt*      listen.tar        smit.script
.sh_history       copyxp/           lamage.cpio.Z     src.224/
PERSONALITY       dwksave/          log.txt           trash/
Personly.dat      ezcomp/           mbox              wisperr.log
Power.dt          eztree/           mftime.cbl        xerox/
STARTUP*          fax/              mjb.grodin/
acutime.cbl       holdit.c          necesito/
alpha_port@       junk.txt          open9ktrack.log
romany|mjb $
</font>

One thing about this directory listing bothers me. I tend to read the listings across from left to right, but you can see that this listing is actually a snaking column. The first entries fill column 1, the next in order start at the top of column 2, and so on. This gets annoying when the directory entry requested is longer than a page, because the top portion of each of the snaking columns appears on the first page.

In order to correct this, replace the -C option with the -x option, which will print entries across rather than down. The following example is the result of ls -AFx; the work we've done already is combined with a left-to-right listing.

<font face="Courier">romany|mjb $ ls -AFx
.exrc             .profile*         .profile.031996*  .sh_history
PERSONALITY       Personly.dat      Power.dt          STARTUP*
acutime.cbl       alpha_port@       amerc/            bin/
contest.txt*      copyxp/           dwksave/          ezcomp/
eztree/           fax/              holdit.c          junk.txt
justio.c          listen/           listen.tar        lamage.cpio.Z
log.txt           mbox              mftime.cbl        mjb.grodin/
necesito/         open9ktrack.log   setdwks           smit.log
smit.script       src.224/          trash/            wisperr.log
xerox/
romany|mjb $
</font>

We're gradually refining our ls options, but there's still one big hole in this latest version. If I want to see entries beginning with l, I would type the command

<font face="Courier">ls -AFx l*
</font>

However, in the result shown below, the output is not at all what I was expecting:

<font face="Courier">romany|mjb $ ls -AFx l*
listen.tar      lamage.cpio.Z   log.txt

listen:
Makefile       atable         cobstat.h      crec.h         crid.a
cstmtest.wcb   ctrlio.c       dio.h          disam.h        dtype.h
filetbl.c*     filetbl.o      gp.h           iocode.h       kcsio.h
kisam.h        kplatfrm.h     kwisp.h        link.c         link.h
ll.c           ll.h           lmxcap.c       lmxcnvrt.wcb   lmxcvt.c
lmxdoc.c       lmxdsp.c       lmxexec.c      lmxfile.c      lmxfld.c
lmxflded.c     lmxflist.c     lmxfrm.c       lmxglb.c       lmxglb.h
lmxlmx.c       lmxload.c      lmxlog.c       lmxmain.c      lmxmenu.c
lmxnaf.c       lmxout.c       lmxparse.c     lmxprs.c       lmxrec.c
lmxsel.c       lmxsort.c      lmxwsel.c      lstr.a         ntable
parminfo.h     readme.txt     rlmx.h         rptglb.h       rptprm.h
rptsrt.h       runcbl.a*      shrthand.h     vscracu.c      vscracu.o
wispscr.c      wispscr.h
romany|mjb $
</font>

Instead of listing the four entries that begin with l, this command lists three files, and then expands the contents of the fourth entry, which is a directory named "listen." What I really wanted was something like this:

<font face="Courier">romany|mjb $ ls -AFx l*
listen/       listen.tar      lamage.cpio.Z   log.txt
</font>

The -d switch

In the normal course of processing, if the file specification (the l* in this example) of an ls command matches a directory, the directory is not simply listed, but is itself expanded. This behavior can be suppressed by using the -d option. Finally, below we get the output that we wanted by using ls -AFxd l*.

<font face="Courier">romany|mjb $ ls -AFxd l*
listen/         listen.tar      lamage.cpio.Z   log.txt
romany|mjb $
</font>

There is a catch to using the -d switch. You must provide something as a filename argument. Try typing ls -AFxd with no argument or filenames and you get back:

<font face="Courier">romany|mjb $ ls -AFxd 
./
romany|mjb $
</font>

What happened to all the files? The ls command without any arguments uses the period (.) as the default argument. Remember, the period is a stand-in for the current directory. Using a simpler version of the command with just the -d switch, you can see what's happening. The command

<font face="Courier">ls -d
</font>

has the period (.) added as the default argument and effectively becomes

<font face="Courier">ls -d . 
</font>

In English this becomes: list the current directory, but don't expand or list its contents. The output of this command is shown below -- the period (.) is not expanded.

<font face="Courier">romany|mjb $ ls -d 
.
romany|mjb $
</font>

The -F flag simply adds the slash after the period as in the earlier example, letting us know that the current directory is a directory. You have to remember this when using the -d switch. Actually, the rule on using -d is a bit longer. If there are no arguments to a command containing the -d switch, or if all the arguments to the command are directories, the directories will not be expanded. For example, attempting to use a -d argument on your home directory will cause this. In the example below, -d provides a directory listing of the $HOME directory, but will not expand its contents:

<font face="Courier">romany|mjb $ ls -d $HOME
/u/mjb
romany|mjb $
</font>

Some other options...

There are two or three additional switches to the ls command that should be part of your arsenal.

The -t switch will list all files by modification time, with the most recently modified listed first, as in the following output of ls -AFxt:

<font face="Courier">romany|mjb $ ls -AFxt
.sh_history       lx*               fax/              wisperr.log
copyxp/           open9ktrack.log   .exrc             listen/
junk.txt          Personly.dat      listen.tar        dwksave/
ezcomp/           bin/              necesito/         smit.log
smit.script       log.txt           setdwks           xerox/
.profile*         trash/            Power.dt          contest.txt*
alpha_port@       mbox              eztree/           .profile.031996*
lamage.cpio.Z     mjb.grodin/       justio.c          mftime.cbl
acutime.cbl       src.224/          amerc/            PERSONALITY
holdit.c          STARTUP*
romany|mjb $
</font>
RELATED TOPICS
1 2 Page
What’s wrong? The new clean desk test
View Comments
You Might Like
Join the discussion
Be the first to comment on this article. Our Commenting Policies