diff options
author | Christian Neukirchen <chneukirchen@gmail.com> | 2015-10-28 12:04:52 +0100 |
---|---|---|
committer | Christian Neukirchen <chneukirchen@gmail.com> | 2015-10-28 12:04:52 +0100 |
commit | 3dbdefe02ade8f7fc47d920bfbf1b49835d7be07 (patch) | |
tree | e15924ace4c3e2c0912b963700ac01c781b4d5a1 | |
parent | f71e7b878a79f0a76f678070a154a0b1b6208e68 (diff) | |
download | lr-3dbdefe02ade8f7fc47d920bfbf1b49835d7be07.tar.gz lr-3dbdefe02ade8f7fc47d920bfbf1b49835d7be07.tar.xz lr-3dbdefe02ade8f7fc47d920bfbf1b49835d7be07.zip |
add prefix stripping, generalize -s
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | lr.c | 42 |
2 files changed, 36 insertions, 11 deletions
diff --git a/README.md b/README.md index 37f953c..dc2c9ea 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Over ls: * `-Q`: don't shell quote file names. * `-d`: don't enter directories. * `-h`: print human readable size for `-l` (also `%s`). -* `-s`: don't print leading `./`. +* `-s`: strip directory prefix passed on command line. * `-x`: don't enter other filesystems. * `-U`: don't sort results. * `-o ORD`: sort according to the string `ORD`, see below. @@ -72,7 +72,8 @@ Over ls: * `%R`: device ID for special files (`stat.st_rdev`). * `%i`: inode number. * `%I`: one space character for every depth level. -* `%p`: full path (without `./` if `-s`). +* `%p`: full path (`%P` if `-s`). +* `%P`: full path without command line argument prefix. * `%l`: symlink target. * `%n`: number of hardlinks. * `%F`: file indicator type symbol (`*/=>@|`). diff --git a/lr.c b/lr.c index 19ce678..2731c67 100644 --- a/lr.c +++ b/lr.c @@ -73,6 +73,7 @@ static char *ordering; static struct expr *expr; static void *root = NULL; // tree static int prune; +static size_t prefixl; static char default_ordering[] = "n"; static char default_format[] = "%p\\n"; @@ -97,6 +98,7 @@ static int uwid, gwid; struct fileinfo { char *fpath; + size_t prefixl; int depth, entries; struct stat sb; off_t total; @@ -980,6 +982,17 @@ print_shquoted(const char *s) } void +print_noprefix(struct fileinfo *fi) +{ + if (strlen(fi->fpath) > fi->prefixl + 1) /* strip prefix */ + print_shquoted(fi->fpath + fi->prefixl + 1); + else if (S_ISDIR(fi->sb.st_mode)) /* turn empty string into "." */ + printf("."); + else /* turn empty string into basename */ + print_shquoted(basenam(fi->fpath)); +} + +void print(const void *nodep, const VISIT which, const int depth) { (void)depth; @@ -1006,9 +1019,12 @@ print(const void *nodep, const VISIT which, const int depth) } else if (*s == '%') { switch (*++s) { case '%': putchar('%'); break; - case 's': if (!hflag) { - printf("%*jd", intlen(maxsize), (intmax_t)fi->sb.st_size); break; - } else /* FALLTHRU */ + case 's': + if (!hflag) { + printf("%*jd", intlen(maxsize), (intmax_t)fi->sb.st_size); + break; + } + /* FALLTHRU */ case 'S': print_human((intmax_t)fi->sb.st_size); break; case 'b': printf("%jd", (intmax_t)fi->sb.st_blocks); break; case 'k': printf("%jd", (intmax_t)fi->sb.st_blocks / 2); break; @@ -1022,9 +1038,14 @@ print(const void *nodep, const VISIT which, const int depth) printf(" "); break; } - case 'p': print_shquoted( - sflag && strncmp(fi->fpath, "./", 2) == 0 ? - fi->fpath+2 : fi->fpath); + case 'p': + if (!sflag) { + print_shquoted(fi->fpath); + break; + } + /* FALLTHRU */ + case 'P': + print_noprefix(fi); break; case 'l': if (S_ISLNK(fi->sb.st_mode)) @@ -1120,6 +1141,7 @@ callback(const char *fpath, const struct stat *sb, int depth, int entries, off_t { struct fileinfo *fi = malloc(sizeof (struct fileinfo)); fi->fpath = strdup(fpath); + fi->prefixl = prefixl; fi->depth = depth; fi->entries = entries; fi->total = total; @@ -1237,12 +1259,14 @@ int traverse(const char *path) { char pathbuf[PATH_MAX + 1]; - size_t l = strlen(path); - if (l > PATH_MAX) { + prefixl = strlen(path); + while (path[prefixl-1] == '/') + prefixl--; + if (prefixl > PATH_MAX) { errno = ENAMETOOLONG; return -1; } - memcpy(pathbuf, path, l + 1); + memcpy(pathbuf, path, prefixl + 1); return recurse(pathbuf, 0); } |