List directories sorted in columns
Larry Cipriani
lvc at cbsck.UUCP
Fri Nov 22 04:51:18 AEST 1985
If you're as impatient as I am you'll appreciate this program.
It lists files sorted in columns, but, because of it's limited
scope, is much faster than the lsc command. It runs on every
version of UNIX I know of.
Larry Cipriani
#!/bin/sh
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
: 'l.c'
echo extracting - 'l.c'
sed 's/^X//' > 'l.c' << 'END_OF_FILE'
X/*
X** This program lists all the file names in <directory>. They
X** are listed in at most five columns. Directories are listed
X** with a terminating /, executables with a terminating *.
X** The current directory is the default directory.
X**
X** usage: l [-a] [directory]
X*/
X
X#include <stdio.h> /* standard i/o package */
X#include <sys/types.h> /* needed for <sys/stat.h> */
X#include <sys/stat.h> /* stat structure declared */
X#include <sys/dir.h> /* direct structure declared */
X
X#define TABSIZ=8
X#define MAXCOL=5 /* maximum number of columns = 80/16 */
X /* 80 = number of columns on terminal */
X /* 16 = DIRSIZ + 2 blanks for spacing */
X
Xchar *malloc(); /* memory allocator - section 3 */
X
Xint copyn(); /* copies s2 to s1, returns number copied */
Xint error(); /* prints an error message */
Xint namecmp(); /* comparison function for file names */
Xint qsort(); /* quicker sort - section 3 */
X
Xchar *progname;
X
Xmain(argc, argv)
X int argc;
X char *argv[];
X{
X int fd, i, aflg;
X int ncols, nrows, nfiles, nstructs, ntabs;
X int col, row, filenum, len, pad;
X char filename[DIRSIZ+1], *fmt1, *fmt2;
X char iobuf[BUFSIZ];
X char *usage = "usage: %s [-a] [directory]\n";
X char *cannot = "%s: cannot %s %s\n";
X char *dir, *dot;
X unsigned dirsize;
X struct direct *head, **headp;
X struct stat stbuf;
X
X aflg = 0;
X dir = (char *)0;
X dot = ".";
X progname = argv[0];
X
X if (argc > 3)
X error(usage, (char *)0, (char *)0);
X
X for (i = 1; i < argc; i++)
X {
X if (strcmp(argv[i], "-a") == 0 && aflg == 0)
X aflg++;
X else
X if (dir == (char *)0)
X dir = argv[i];
X else
X error(usage, (char *)0, (char *)0);
X }
X
X if (dir == (char *)0)
X dir = dot;
X else
X if (chdir(dir) == -1)
X error(cannot, "chdir", dir);
X
X if ((fd = open(dot , 0)) == -1)
X error(cannot, "open", dir);
X
X if (stat(dot, &stbuf) == -1)
X error(cannot, "stat", dir);
X
X setbuf(stdout, iobuf);
X
X dirsize = (unsigned)stbuf.st_size;
X nstructs = dirsize/sizeof(struct direct);
X head = (struct direct *)malloc(dirsize);
X if (read(fd, (char *)head, dirsize) == -1)
X error(cannot, "read", dir);
X headp = (struct direct **)malloc(sizeof(struct direct **) * nstructs);
X
X /* set up pointers only to the files to be listed */
X
X if (aflg)
X {
X for (nfiles = i = 0; i < nstructs; i++)
X if (head[i].d_ino != (ino_t)0)
X headp[nfiles++] = &head[i];
X }
X else
X {
X for (nfiles = i = 0 ; i < nstructs; i++)
X if (head[i].d_ino != (ino_t)0 &&
X head[i].d_name[0] != '.')
X headp[nfiles++] = &head[i];
X }
X
X if (nfiles == 0)
X exit(0);
X
X /* sort only the pointers */
X
X qsort((char *)headp, nfiles, (int)sizeof(struct direct **), namecmp);
X
X nrows = nfiles / MAXCOL + (nfiles % MAXCOL ? 1 : 0);
X ncols = nfiles / nrows + (nfiles % nrows ? 1 : 0);
X
X for (row = 0; row < nrows; row++)
X {
X for (col = 0; col < ncols; col++)
X {
X if ((filenum = col*nrows + row) >= nfiles)
X continue;
X
X len = copyn(filename, headp[filenum]->d_name, DIRSIZ);
X
X stat(filename, &stbuf);
X
X if (stbuf.st_mode & S_IFDIR)
X {
X pad = 1;
X fmt1 = "%s/\n";
X fmt2 = "%.*s/%.*s";
X }
X else
X if (stbuf.st_mode & S_IEXEC)
X {
X pad = 1;
X fmt1 = "%s*\n";
X fmt2 = "%.*s*%.*s";
X }
X else
X {
X pad = 2;
X fmt1 = "%s\n";
X fmt2 = "%.*s%.*s";
X }
X
X if ((col == ncols - 1) || (filenum + nrows >= nfiles))
X fprintf(stdout, fmt1, filename);
X else
X {
X ntabs = ((DIRSIZ+pad-len) > TABSIZ ? 2 : 1);
X fprintf(stdout, fmt2, len,
X filename, ntabs, "\t\t");
X }
X }
X fflush(stdout); /* write the row out */
X }
X
X exit(0);
X}
X
X/*
X** Sorts the file names in alphabetical order.
X*/
X
Xint namecmp(pp1, pp2)
X struct direct **pp1, **pp2;
X{
X register struct direct *p1 = *pp1;
X register struct direct *p2 = *pp2;
X
X return(strncmp(&p1->d_name[0], &p2->d_name[0], DIRSIZ));
X}
X
X/*
X** Copies s2 to s1 until n characters have been copied
X** or the null of s2 is reached, whichever occurs sooner.
X** Returns the number of non-null characters copied,
X** and s1 is null terminated.
X*/
X
Xint copyn(s1, s2, n)
X register char *s1, *s2;
X register int n;
X{
X register int i;
X
X for (i = 0 ; i < n; i++)
X if ((*s1++ = *s2++) == '\0')
X return(i);
X *s1 = '\0';
X return(i);
X}
X
Xerror(format, verb, noun)
X char *format, *verb, *noun;
X{
X fprintf(stderr, format, progname, verb, noun);
X exit(-1);
X}
END_OF_FILE
Larry Cipriani cbscc!lvc
More information about the Comp.sources.unix
mailing list