bigfiles - list the largest files under these directories

Name
       bigfiles - list the largest files under these directories

Syntax
       bigfiles [-nn] [directory...]

Description
       Bigfiles  recursively  scans directory for file sizes, keeping track of
       the biggest files. At the end of the scan, it wites the size  and  file
       names of the biggest nn files.

Arguments
       -nn  Limit  the listing to the biggest nn files (100 is the default and
       maximum)

       -s Restrict search to the same file system as first directory.

       directory Examine these directories. Several may be  specified.  If  no
       directories  are  specified, filenames are read from stdin. This allows
       input to be piped from a program such as find.

Example
       $ bigfiles -5 .
          1306624  ./ULTRIX/dxuil
           989488  ./ULTRIX/docclient
           372736  ./ULTRIX/xviewgl
           278528  ./ULTRIX/sc
           106470  ./sun4c/xanim
       $ /bin/ls *~ | bigfiles
             3061  recent.c~
             2003  tree.c~
              962  ingwho~
              707  diskinfo~
              401  dstats~
              258  do_sum.c~
              248  rgrep~
               54  mif2txt~

See Also
       stat(2)
Known Bugs
       The switch handling doesn't allow piped filenames and a  limit  on  the
       number of files reported.

       Only regular files are considered.

Author
       David Horton - CiTR

Copyright
       Centre for Information Technology Research, 1993

/* Bigfiles - finds the large files on a system.
    If no arguments are provided, then filenames are read from standard input
    otherwise, the arguments are considered to be directory names

    David Horton,
    Centre for Information Technology Research,
    University of Queensland
    horton@citr.uq.oz.au
*/

#include <stdio.h>
#define _INCLUDE_POSIX_SOURCE       /* HP/UX */
#include <sys/types.h>
#define _INCLUDE_HPUX_SOURCE        /* HP/UX */
#define _INCLUDE_XOPEN_SOURCE       /* HP/UX */
#include <sys/stat.h>
#include <memory.h>
#include <dirent.h>
#define MF 200
#define FNLEN 2000
#if !defined(S_ISLNK)
#  define S_ISLNK(_M) ((_M & S_IFMT)==S_IFMT)   /* test for symbolic link */
#endif
#include <stdlib.h>
#ifdef void
#error
#endif


#ifdef gets
#undef gets
#endif
#define gets(b) fgets(b, sizeof(b), stdin)

struct context {        /* context we need to keep for a possibly big file */
        off_t   size;
        char    name[FNLEN];
};

struct context c[MF];   /* array of biggest files so far, sorted */

char    device_mode     = '\0'; /* s means will be only one device,
                                                           S means device set */
dev_t   device = 0;                     /* the device number */

#ifdef __STDC__
void big (off_t st_size, char *fname) {       /* see if this is a big file */
#else
void big (st_size, fname)     /* see if this is a big file */
off_t st_size; char *fname; { /* see if this is a big file */
#endif

    int i;
       /*printf("big(%d,%s)\n", (int) st_size, fname); */

    for (i = MF-1; i >= 0; i--) {       /* starting from the smallest we have*/
        if (c[i].size >= st_size)       /* see if bigger                     */
                break;
        else {
            if ( i != (MF-1)) {         /* if it is shuffle into place       */
                c[i+1].size = c[i].size;
                memcpy(c[i+1].name,c[i].name,sizeof(c[i].name));
            }
        }
    }
    if ( i != MF-1) {                   /* final test for top of the tree    */
        c[i+1].size = st_size;
        memcpy(c[i+1].name,fname,sizeof(c[i+1].name));
    }
}

#if defined(__STDC__)
void tree(char *root) {                 /* Process a unix directory instead of*/
#else
void tree(root)                       /* Process a unix directory instead of*/
char *root; {                 /* Process a unix directory instead of*/
#endif

        DIR *dirp;                      /* a list of filenames on stdin       */
        struct dirent *dp;
        struct stat s;
        char    buf[FNLEN];

       /*printf("tree(%s)\n", root); */

        dirp = opendir(root);           /* Open the top of the directory tree */
        if (dirp == NULL) {
                perror(root);
                return;         /* Cannot open */
        }
        while ((dp = readdir(dirp)) != NULL) {  /*process entries in directory*/
                if ( strcmp(dp->d_name, ".") == 0)
                    continue;           /* don't go infinite */
                if ( strcmp(dp->d_name, "..") == 0)
                    continue;           /* don't go up */
                sprintf(buf,"%s/%s", root, dp->d_name);
                                if (lstat(buf,&s)) {
                                        continue;       /* no data available */
                                }
                                switch (device_mode) {
                                case 's':
                                        device = s.st_dev;
                                        device_mode = 'S';
                                        break;
                                case 'S':
                                        if (s.st_dev != device) {
                                                continue;
                                        }
                                        break;
                                default:
                                        break;
                                }
                if (S_ISLNK(s.st_mode))
                        continue;       /* don't follow symbolic links */
                if (S_ISDIR(s.st_mode)) {   /* go down sub-tree */
                    tree(buf);
                }
                if (!S_ISREG(s.st_mode)) {  /* only look at regular files */
                        continue;
                }
                big(s.st_size, buf);            /* see if big file or not */
        }
        (void) closedir(dirp);
 }

static char Copyright[] = "@(#) Copyright 1994, David Horton";
static char rcs[] = "@(#)$RCSfile$ $Revision$";

#if defined(__STDC__)
void main(int argc, char *argv[]) {
#else
main(argc, argv)
int argc; char *argv[]; {
#endif

        struct stat     s;

        char    fname[FNLEN];                   /* buffer for filename */
        char    *fn;
        int             i;
        int             many = MF;
        int             dirs = 0;

        memset(c, 0, sizeof(c));

        if (argc == 1) {            /* no args -> read filenames from stdin */

            while ( (fn = gets(fname)) != NULL) {
                        s.st_size = 0;
                        if (lstat(fname,&s)) {
                                continue;       /* no data available */
                        }
            if (!S_ISREG(s.st_mode)) {  /* only look at regular files */
                        continue;
                        }
            big(s.st_size, fname);
            }
        } else {                /* otherwise a list of directory heads */
            for (i = 1; i < argc; i++) {
                                if (argv[i][0] == '-') {
                                        switch(argv[i][1]) {
                                        case 's': case 'S':
                                                device_mode = 's';
                                                break;
                                        case 'h':
                                                fprintf(stderr,
                                                        "Usage: %s [-h] [-v] [-s] [directory]...\n",argv[0]);
                                                exit(0);
                                                break;
                                        case 'v':
                                                fprintf(stderr, "%s : %s\n",argv[0], Copyright);
                                                fprintf(stderr, "%s\n", rcs);
                                                exit(0);
                                                break;
                                        default:
                                                many = - atoi(argv[i]);
                                                if ((many ==0) || (many > MF))
                                                        many = MF;
                                                continue;
                                        }
                                }
                                tree(argv[i]);
                                dirs ++;
            }
        }

        for( i=0; i < many; i++) {
                if (c[i].size == 0) break;
                printf("%10d  %s\n",(int)c[i].size,c[i].name);
        }

        exit (0);
}