about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-07-24 17:38:00 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-07-24 17:38:00 +0200
commit9098bbd6fc49154980c07e7c401acd799fb92773 (patch)
tree25ee4c707566da072938cf734852d0d3a25dd638
parentadca1c80f1116c12d1e034c2c1272b9826e49ef2 (diff)
downloadlr-9098bbd6fc49154980c07e7c401acd799fb92773.tar.gz
lr-9098bbd6fc49154980c07e7c401acd799fb92773.tar.xz
lr-9098bbd6fc49154980c07e7c401acd799fb92773.zip
lr: argument '-' means read files from standard input
-rw-r--r--NEWS.md4
-rw-r--r--README.md4
-rw-r--r--lr.111
-rw-r--r--lr.c37
4 files changed, 55 insertions, 1 deletions
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";
@@ -1816,9 +1817,43 @@ recurse(char *path, struct history *h)
 }
 
 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;