summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2017-07-21 17:46:02 -0400
committerTavian Barnes <tavianator@tavianator.com>2017-07-21 17:49:16 -0400
commit4a245d3885f99169649cc45e2d1abe606c249d22 (patch)
tree283dc9f8a88a29a9434bb05f6ae86a98190b0559
parent49fa21d023feb89e236ad4d655d96dde3574560e (diff)
downloadbfs-4a245d3885f99169649cc45e2d1abe606c249d22.tar.xz
Implement -printx
Also from NetBSD.
-rw-r--r--bfs.h1
-rw-r--r--eval.c38
-rw-r--r--parse.c16
-rwxr-xr-xtests.sh5
-rw-r--r--tests/test_printx.out21
5 files changed, 81 insertions, 0 deletions
diff --git a/bfs.h b/bfs.h
index cc00f6b..16ce475 100644
--- a/bfs.h
+++ b/bfs.h
@@ -326,6 +326,7 @@ bool eval_fls(const struct expr *expr, struct eval_state *state);
bool eval_fprint(const struct expr *expr, struct eval_state *state);
bool eval_fprint0(const struct expr *expr, struct eval_state *state);
bool eval_fprintf(const struct expr *expr, struct eval_state *state);
+bool eval_fprintx(const struct expr *expr, struct eval_state *state);
bool eval_prune(const struct expr *expr, struct eval_state *state);
bool eval_quit(const struct expr *expr, struct eval_state *state);
diff --git a/eval.c b/eval.c
index 34ccba8..1d2da7c 100644
--- a/eval.c
+++ b/eval.c
@@ -670,6 +670,44 @@ done:
}
/**
+ * -printx action.
+ */
+bool eval_fprintx(const struct expr *expr, struct eval_state *state) {
+ FILE *file = expr->cfile->file;
+ const char *path = state->ftwbuf->path;
+
+ while (true) {
+ size_t span = strcspn(path, " \t\n\\$'\"`");
+ if (fwrite(path, 1, span, file) != span) {
+ goto error;
+ }
+ path += span;
+
+ char c = path[0];
+ if (!c) {
+ break;
+ }
+
+ char escaped[] = {'\\', c};
+ if (fwrite(escaped, 1, sizeof(escaped), file) != sizeof(escaped)) {
+ goto error;
+ }
+ ++path;
+ }
+
+
+ if (fputc('\n', file) == EOF) {
+ goto error;
+ }
+
+ return true;
+
+error:
+ eval_error(state);
+ return true;
+}
+
+/**
* -prune action.
*/
bool eval_prune(const struct expr *expr, struct eval_state *state) {
diff --git a/parse.c b/parse.c
index f5bb5e1..d4e945c 100644
--- a/parse.c
+++ b/parse.c
@@ -1699,6 +1699,18 @@ static struct expr *parse_printf(struct parser_state *state, int arg1, int arg2)
}
/**
+ * Parse -printx.
+ */
+static struct expr *parse_printx(struct parser_state *state, int arg1, int arg2) {
+ struct expr *expr = parse_nullary_action(state, eval_fprintx);
+ if (expr) {
+ expr->always_true = true;
+ expr->cfile = state->cmdline->cout;
+ }
+ return expr;
+}
+
+/**
* Parse -prune.
*/
static struct expr *parse_prune(struct parser_state *state, int arg1, int arg2) {
@@ -2178,6 +2190,9 @@ static struct expr *parse_help(struct parser_state *state, int arg1, int arg2) {
cfprintf(cout, " %{blu}-exit%{rs} %{bld}[STATUS]%{rs}\n");
cfprintf(cout, " Exit immediately with the given status (%d if unspecified)\n", EXIT_SUCCESS);
+ cfprintf(cout, " %{blu}-printx%{rs}\n");
+ cfprintf(cout, " Like %{blu}-print%{rs}, but escape whitespace and quotation characters, to make the\n");
+ cfprintf(cout, " output safe for %{ex}xargs%{rs}. Consider using %{blu}-print0%{rs} and %{ex}xargs%{rs} %{bld}-0%{rs} instead.\n");
cfprintf(cout, " %{blu}-rm%{rs}\n");
cfprintf(cout, " Delete any found files (same as %{blu}-delete%{rs}; implies %{blu}-depth%{rs})\n\n");
@@ -2299,6 +2314,7 @@ static const struct table_entry parse_table[] = {
{"-print", false, parse_print},
{"-print0", false, parse_print0},
{"-printf", false, parse_printf},
+ {"-printx", false, parse_printx},
{"-prune", false, parse_prune},
{"-quit", false, parse_quit},
{"-readable", false, parse_access, R_OK},
diff --git a/tests.sh b/tests.sh
index f0ada64..d7e9287 100755
--- a/tests.sh
+++ b/tests.sh
@@ -256,6 +256,7 @@ bsd_tests=(
test_nogroup
test_nouser
test_exit
+ test_printx
)
gnu_tests=(
@@ -1227,6 +1228,10 @@ function test_exit() {
bfs_diff basic -name bar -exit -o -print
}
+function test_printx() {
+ bfs_diff weirdnames -printx
+}
+
passed=0
failed=0
diff --git a/tests/test_printx.out b/tests/test_printx.out
new file mode 100644
index 0000000..53c7547
--- /dev/null
+++ b/tests/test_printx.out
@@ -0,0 +1,21 @@
+weirdnames
+weirdnames/!
+weirdnames/!-
+weirdnames/(
+weirdnames/(-
+weirdnames/)
+weirdnames/,
+weirdnames/-
+weirdnames/...
+weirdnames/\
+weirdnames/\\
+weirdnames/!-/e
+weirdnames/!/d
+weirdnames/(-/c
+weirdnames/(/b
+weirdnames/)/g
+weirdnames/,/f
+weirdnames/-/a
+weirdnames/.../h
+weirdnames/\ /j
+weirdnames/\\/i