diff options
author | Christian Neukirchen <chneukirchen@gmail.com> | 2016-02-26 13:04:32 +0100 |
---|---|---|
committer | Christian Neukirchen <chneukirchen@gmail.com> | 2016-02-26 13:04:32 +0100 |
commit | 8b228c157f48718d7dbab8828145609e879d126a (patch) | |
tree | 6e92e83eb3f38cd9144479ade83d900879d122d1 | |
parent | b2bfdf1c9f7fa149790eda8bb51dda56412d6b80 (diff) | |
download | lr-8b228c157f48718d7dbab8828145609e879d126a.tar.gz lr-8b228c157f48718d7dbab8828145609e879d126a.tar.xz lr-8b228c157f48718d7dbab8828145609e879d126a.zip |
count directory entries when needed
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | lr.1 | 5 | ||||
-rw-r--r-- | lr.c | 31 |
3 files changed, 33 insertions, 7 deletions
diff --git a/README.md b/README.md index 7bb4083..d40daf8 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Over ls: * `-S`: BSD stat(1)-inspired output. * `-f FMT`: custom formatting, see below. * `-D`: depth first traversal. `prune` does not work, but `entries` - and `total` is computed. + and `total` are computed on the fly. * `-H`: only follow symlinks on command line. * `-L`: follow all symlinks. * `-1`: don't go below one level of directories. @@ -94,7 +94,7 @@ Over ls: * `%G`: numeric gid. * `%u`: user name. * `%U`: numeric uid. -* `%e`: number of entries in directories (only with `-D`). +* `%e`: number of entries in directories. * `%t`: total size used by accepted files in directories (only with `-D`). * `%Y`: type of the filesystem the file resides on. * `%x`: Linux-only: a combination of: `#` for files with security capabilities, `+` for files with an ACL, `@` for files with other extended attributes. diff --git a/lr.1 b/lr.1 index de8a56b..6c31017 100644 --- a/lr.1 +++ b/lr.1 @@ -43,7 +43,7 @@ will not work, but .Ic entries and .Ic total -is computed. +are computed on the fly. .It Fl H Only follow symlinks on command line (default: don't follow symlinks). .It Fl L @@ -156,8 +156,7 @@ User name .It Ic \&%U Numeric uid .It Ic \&%e -Number of entries in directories (only with -.Fl D ) +Number of entries in directories .It Ic \&%t Total size used by accepted files in directories (only with .Fl D ) diff --git a/lr.c b/lr.c index ee3119a..3fd66a7 100644 --- a/lr.c +++ b/lr.c @@ -1009,6 +1009,33 @@ xattr_string(const char *f) #endif } +static nlink_t +count_entries(struct fileinfo *fi) +{ + nlink_t c = 0; + struct dirent *de; + DIR *d; + + if (Dflag) + return fi->entries; + + if (!S_ISDIR(fi->sb.st_mode)) + return 0; + + d = opendir(fi->fpath); + if (!d) + return 0; + while ((de = readdir(d))) { + if (de->d_name[0] == '.' && + (!de->d_name[1] || (de->d_name[1]=='.' && !de->d_name[2]))) + continue; + c++; + } + closedir(d); + + return c; +} + int eval(struct expr *e, struct fileinfo *fi) { @@ -1038,7 +1065,7 @@ eval(struct expr *e, struct fileinfo *fi) case PROP_CTIME: v = fi->sb.st_ctime; break; case PROP_DEPTH: v = fi->depth; break; case PROP_DEV: v = fi->sb.st_dev; break; - case PROP_ENTRIES: v = fi->entries; break; + case PROP_ENTRIES: v = count_entries(fi); break; case PROP_GID: v = fi->sb.st_gid; break; case PROP_INODE: v = fi->sb.st_ino; break; case PROP_LINKS: v = fi->sb.st_nlink; break; @@ -1520,7 +1547,7 @@ print_format(struct fileinfo *fi) case 'u': printf("%*s", -uwid, username(fi->sb.st_uid)); break; case 'U': printf("%*ld", intlen(maxuid), (long)fi->sb.st_uid); break; - case 'e': printf("%ld", (long)fi->entries); break; + case 'e': printf("%ld", (long)count_entries(fi)); break; case 't': printf("%jd", (intmax_t)fi->total); break; case 'Y': printf("%*s", -fwid, fstype(fi->sb.st_dev)); break; case 'x': printf("%*s", -maxxattr, fi->xattr); break; |