From b5344dac304b5938d8a41c91bf6c1e2dc00d8984 Mon Sep 17 00:00:00 2001 From: David Peter Date: Sun, 8 Aug 2021 22:49:32 +0200 Subject: [PATCH] Improve -x/-X help text and man page description closes #605 --- doc/fd.1 | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/app.rs | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/doc/fd.1 b/doc/fd.1 index 7824987..bff3b0e 100644 --- a/doc/fd.1 +++ b/doc/fd.1 @@ -259,12 +259,22 @@ Provide paths to search as an alternative to the positional \fIpath\fR argument. \'fd [FLAGS/OPTIONS] \-\-search\-path PATH \-\-search\-path PATH2 [PATTERN]\' .TP .BI "\-x, \-\-exec " command +.RS Execute .I command -for each search result in parallel (use --threads=1 for sequential command execution). The following placeholders are substituted by a path derived from the current search result: +for each search result in parallel (use --threads=1 for sequential command execution). + +Note that all subsequent positional arguments are considered to be arguments to the +.I command +- not to fd. +It is therefore recommended to place the \-x/\-\-exec option last. Alternatively, you can supply +a ';' argument to end the argument list and continue with more fd options. +Most shells require ';' to be escaped: '\\;'. + +The following placeholders are substituted before the command is executed: .RS .IP {} -path +path (of the current search result) .IP {/} basename .IP {//} @@ -274,15 +284,33 @@ path without file extension .IP {/.} basename without file extension .RE + +If no placeholder is present, an implicit "{}" at the end is assumed. + +Examples: + + - find all *.zip files and unzip them: + + fd -e zip -x unzip + + - find *.h and *.cpp files and run "clang-format -i .." for each of them: + + fd -e h -e cpp -x clang-format -i + + - Convert all *.jpg files to *.png files: + + fd -e jpg -x convert {} {.}.png +.RE .TP .BI "\-X, \-\-exec-batch " command +.RS Execute .I command -with all search results at once. -A single occurence of the following placeholders is authorized and substituted by the paths derived from the search results before the command is executed: +once, with all search results as arguments. +One of the following placeholders is substituted before the command is executed: .RS .IP {} -path +path (of all search results) .IP {/} basename .IP {//} @@ -292,6 +320,22 @@ path without file extension .IP {/.} basename without file extension .RE + +If no placeholder is present, an implicit "{}" at the end is assumed. + +Examples: + + - Find all test_*.py files and open them in your favorite editor: + + fd -g 'test_*.py' -X vim + + Note that this executes a single "vim" process with all search results as arguments. + + - Find all *.rs files and count the lines with "wc -l ...": + + fd -e rs -X wc -l +.RE + .SH PATTERN SYNTAX The regular expression syntax used by fd is documented here: diff --git a/src/app.rs b/src/app.rs index 5781daa..2d6ec94 100644 --- a/src/app.rs +++ b/src/app.rs @@ -298,16 +298,24 @@ pub fn build_app() -> App<'static, 'static> { .conflicts_with("list-details") .help("Execute a command for each search result") .long_help( - "Execute a command for each search result in parallel (use --threads=1 for sequential command execution).\n\ - All arguments following --exec are taken to be arguments to the command until the \ - argument ';' is encountered.\n\ - Each occurrence of the following placeholders is substituted by a path derived from the \ - current search result before the command is executed:\n \ - '{}': path\n \ + "Execute a command for each search result in parallel (use --threads=1 for sequential command execution). \ + All positional arguments following --exec are considered to be arguments to the command - not to fd. \ + It is therefore recommended to place the '-x'/'--exec' option last.\n\ + The following placeholders are substituted before the command is executed:\n \ + '{}': path (of the current search result)\n \ '{/}': basename\n \ '{//}': parent directory\n \ '{.}': path without file extension\n \ - '{/.}': basename without file extension", + '{/.}': basename without file extension\n\n\ + If no placeholder is present, an implicit \"{}\" at the end is assumed.\n\n\ + Examples:\n\n \ + - find all *.zip files and unzip them:\n\n \ + fd -e zip -x unzip\n\n \ + - find *.h and *.cpp files and run \"clang-format -i ..\" for each of them:\n\n \ + fd -e h -e cpp -x clang-format -i\n\n \ + - Convert all *.jpg files to *.png files:\n\n \ + fd -e jpg -x convert {} {.}.png\ + ", ), ) .arg( @@ -321,16 +329,20 @@ pub fn build_app() -> App<'static, 'static> { .conflicts_with_all(&["exec", "list-details"]) .help("Execute a command with all search results at once") .long_help( - "Execute a command with all search results at once.\n\ - All arguments following --exec-batch are taken to be arguments to the command until the \ - argument ';' is encountered.\n\ - A single occurrence of the following placeholders is authorized and substituted by the paths derived from the \ - search results before the command is executed:\n \ - '{}': path\n \ + "Execute the given command once, with all search results as arguments.\n\ + One of the following placeholders is substituted before the command is executed:\n \ + '{}': path (of all search results)\n \ '{/}': basename\n \ '{//}': parent directory\n \ '{.}': path without file extension\n \ - '{/.}': basename without file extension", + '{/.}': basename without file extension\n\n\ + If no placeholder is present, an implicit \"{}\" at the end is assumed.\n\n\ + Examples:\n\n \ + - Find all test_*.py files and open them in your favorite editor:\n\n \ + fd -g 'test_*.py' -X vim\n\n \ + - Find all *.rs files and count the lines with \"wc -l ...\":\n\n \ + fd -e rs -X wc -l\ + " ), ) .arg(