From 4a245d3885f99169649cc45e2d1abe606c249d22 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 21 Jul 2017 17:46:02 -0400 Subject: Implement -printx Also from NetBSD. --- bfs.h | 1 + eval.c | 38 ++++++++++++++++++++++++++++++++++++++ parse.c | 16 ++++++++++++++++ tests.sh | 5 +++++ tests/test_printx.out | 21 +++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 tests/test_printx.out 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 @@ -669,6 +669,44 @@ done: return true; } +/** + * -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. */ diff --git a/parse.c b/parse.c index f5bb5e1..d4e945c 100644 --- a/parse.c +++ b/parse.c @@ -1698,6 +1698,18 @@ static struct expr *parse_printf(struct parser_state *state, int arg1, int arg2) return expr; } +/** + * 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. */ @@ -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 -- cgit v1.2.3