From 9098bbd6fc49154980c07e7c401acd799fb92773 Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Sun, 24 Jul 2016 17:38:00 +0200 Subject: lr: argument '-' means read files from standard input --- NEWS.md | 4 ++++ README.md | 4 ++++ lr.1 | 11 +++++++++++ lr.c | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index a0fbf07..5cad279 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +## HEAD + +* Feature: argument '-' means read files from standard input + ## 0.3.2 (2016-05-20) * Bug: getopt was called in a wrong way from ARM platforms diff --git a/README.md b/README.md index 49dc30c..60243bc 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,11 @@ Over ls: lr [-0|-F|-l [-TA|-TC|-TM]|-S|-f FMT] [-D] [-H|-L] [-1AGQdhsx] [-U|-o ORD] [-t TEST]* PATH... +The special path argument `-` makes `lr` read file names from standard +input, instead of traversing path. + * `-0`: output filenames seperated by NUL bytes (implies `-Q`). + Likewise, read input filenames seperated by NUL bytes. * `-F`: output filenames and an indicator of their file type (`*/=>@|`). * `-l`: long output ala `ls -l`. * `-TA`: with `-l`, output atime. diff --git a/lr.1 b/lr.1 index 9f88a98..8a9ecee 100644 --- a/lr.1 +++ b/lr.1 @@ -19,11 +19,22 @@ is a versatile tool to generate file listings with configurable formatting, ordering and filtering. .Pp +The special +.Ar path +argument +.Ic \&- +makes +.Nm +read file names from standard input, +instead of traversing +.Ar path . +.Pp The options are as follows: .Bl -tag -width Ds .It Fl 0 Output filenames seperated by NUL bytes (implies .Fl Q ) . +Likewise, read input filenames seperated by NUL bytes. .It Fl F Output filenames and an indicator of their file type (one of .Sq Li */=>@| ) . diff --git a/lr.c b/lr.c index 5a64d9f..777b137 100644 --- a/lr.c +++ b/lr.c @@ -81,6 +81,7 @@ static struct expr *expr; static void *root = NULL; // tree static int prune; static size_t prefixl; +static char input_delim = '\n'; static char default_ordering[] = "n"; static char default_format[] = "%p\\n"; @@ -1815,10 +1816,44 @@ recurse(char *path, struct history *h) return 0; } +int +traverse_file(FILE *file) +{ + char *line = 0; + size_t linelen = 0; + struct stat st; + ssize_t rd; + + while (1) { + errno = 0; + rd = getdelim(&line, &linelen, input_delim, file); + if (rd == -1) { + if (errno != 0) + return -1; + break; + } + + if (rd > 0 && line[rd-1] == input_delim) // strip delimiter + line[rd-1] = 0; + + if (Lflag ? stat(line, &st) : lstat(line, &st) < 0) + continue; + + callback(line, &st, 0, 0, 0); + } + + free(line); + return 0; +} + int traverse(const char *path) { char pathbuf[PATH_MAX + 1]; + + if (path[0] == '-' && !path[1]) + return traverse_file(stdin); + prefixl = strlen(path); while (path[prefixl-1] == '/') prefixl--; @@ -1852,7 +1887,7 @@ main(int argc, char *argv[]) while ((c = getopt(argc, argv, "01ADFGHLQST:Udf:lho:st:x")) != -1) switch(c) { - case '0': format = zero_format; Qflag++; break; + case '0': format = zero_format; input_delim = 0; Qflag++; break; case '1': expr = chain(parse_expr("depth == 0 || prune"), EXPR_AND, expr); break; case 'A': expr = chain(parse_expr("!(path ~~ \"*/.*\" && prune) && !path == \".\""), EXPR_AND, expr); break; case 'D': Dflag++; break; -- cgit 1.4.1