Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the '--exec' help text #605

Open
sharkdp opened this issue May 25, 2020 · 11 comments
Open

Improve the '--exec' help text #605

sharkdp opened this issue May 25, 2020 · 11 comments

Comments

@sharkdp
Copy link
Owner

@sharkdp sharkdp commented May 25, 2020

I see a lot of fd users that seem to think that they need to add "{}" to all commands. Some users also seem to think that the closing semicolon (which needs to be escaped) \; is required:

fd … -x command "{}" \;

In reality, 90% of the --exec use cases can be written without the "{}" part (which fd adds, if it is ommitted) because the file entry often comes last. The semicolon is never required if we teach users to put the --exec argument last.

I would like to improve several things in the documentation:

  • the README section "Parallel command execution" should be merged with the tutorial section. We should put less focus on teaching the {}/{.}/{/}/… syntax and show more simple examples like fd … -x wc -l or fd … -X vim first.
  • The --help text and the man page should also be updated accordingly. I think two or three simple examples should also go inside the --help text and definitely into the man page.
@ericonr
Copy link

@ericonr ericonr commented Jun 1, 2020

Do you think the size of the explanations for {} and friends should be smaller? I quite like them as they are, tbh.

The examples should be the same for the man pages and the help output right?

@sharkdp
Copy link
Owner Author

@sharkdp sharkdp commented Jun 2, 2020

Do you think the size of the explanations for {} and friends should be smaller? I quite like them as they are, tbh.

I would not make the text on this less detailed. I just would like it to be a little bit less in the spotlight. It's not the first thing users should learn when reading about --exec. I think they should see a few easy examples (and most common use cases) first.

The examples should be the same for the man pages and the help output right?

Yes

@Piraty
Copy link

@Piraty Piraty commented Jun 5, 2020

the manpage definitely needs more attention regarding -x, it doesn't even mention the semicolon to end the command. I thought enclosing the command in quotes " would make sense as well?

@sharkdp
Copy link
Owner Author

@sharkdp sharkdp commented Jun 5, 2020

the manpage definitely needs more attention regarding -x, it doesn't even mention the semicolon to end the command.

👍

I thought enclosing the command in quotes " would make sense as well?

Hm, not necessarily. fd … -x wc -l is correct. fd … -x "wc -l" will not work. fd … -x "wc" "-l" is fine, but not really needed.

@Piraty
Copy link

@Piraty Piraty commented Jun 6, 2020

i was fooled by both the manpage and --help's output, because they mention all options args are required to be before pattern and path (which none of your examples using -x adhere to), hence i assumed -x takes a string (as in: single argument, enclosed in "). would that have made parsing much easier, wouldn't it? Also more intuitive

@sharkdp
Copy link
Owner Author

@sharkdp sharkdp commented Jun 6, 2020

i was fooled by both the manpage and --help's output, because they mention all options args are required to be before pattern and path

Hm, true. On the other hand, most "USAGE"/"SYNOPSIS" sections are written like this, even if the programs support flags/options after the positional arguments. Take ls, for example:

SYNOPSIS
       ls [OPTION]... [FILE]...

It still supports things like ls FILE -l though.

In fact, I think this is a quite essential feature for a command line interface. It allows users to easily repeat the last command while adding a new option (without having to move the cursor in front of the position arguments).

If you think we should improve the documentation in this respect, let us know.

hence i assumed -x takes a string

I can definitely see why you would think that. Let's add this to the list of things that should be improved in this ticket.

would that have made parsing much easier, wouldn't it? Also more intuitive

It would have made (this part of) parsing easier, yes. We still decided against this. There are several reasons:

  • If we would have accepted a string like "wc -l" or something more complicated like "echo -n \"found search result {}\", " as an argument, we would have had two options: (1) use an intermediate shell to execute the command. this would have resulted in a drastic performance regression for fast-running commands. (2) we could have tried to parse the string ourselves, splitting it up into separate arguments in order to properly start the child process.
  • Since file names can contain all sorts of characters (a space, a newline, a quote), we would need to know how to escape these characters when replacing patterns like {} in the command string (in both cases above!). I'm pretty sure that this is an impossible task in general. Just imagine someone wants to execute convert '{}' "{/}.png" while some search results contain a ' character and some others contain a " character. By implementing -x the way we did it, we leave all of this to the users shell. Without any nasty surprises for the user.
  • I like that I can type fd … -x wc -l instead of fd … -x "wc -l".
@tmccombs
Copy link
Collaborator

@tmccombs tmccombs commented Jun 7, 2020

In fact, I think this is a quite essential feature for a command line interface. It allows users to easily repeat the last command while adding a new option (without having to move the cursor in front of the position arguments).

Totally agree. I've encountered programs that absolutely require options to come before arguments, and found it very annoying.

@Piraty
Copy link

@Piraty Piraty commented Jun 15, 2020

sure, but passing a string feels natural, no matter the position

@mbhall88
Copy link

@mbhall88 mbhall88 commented Jun 17, 2020

Would you consider also adding an example of using --exec with a command that redirects its output to stdout and saves as a file? I personally just ran into this and it took me a little while to figure it out. So an example in the docs might be nice. I got my solution (in part) from this SO question.

A somewhat trivial example of cating all text files below the current directory into a file with the same name in the directory above.

via a script

cat.sh

#!/usr/bin/env sh
cat "$1" > "$2"
$ fd -e .txt --exec ./cat.sh {} ../{/} \; . .

one-liner

$ fd -e .txt --exec sh -c "cat {} > ../{/}" \; . .

I appreciate there may be a better way of doing this that I haven't figured out.

@sharkdp
Copy link
Owner Author

@sharkdp sharkdp commented Jun 17, 2020

Using an intermediate shell script is the best option here, I believe. Your first version is fine, but could be simplified to (this is what this ticket is about):

$ fd -e .txt --exec ./cat.sh {} ../{/}

The one-liner is not equivalent and will fail for more complex filenames with spaces, for example. Using --exec sh -c "cat '{}' > ../'{/}'" would be a bit safer, but can still fail for filenames involving quotes.

@sharkdp
Copy link
Owner Author

@sharkdp sharkdp commented Jun 17, 2020

@Piraty

sure, but passing a string feels natural, no matter the position

Maybe, but I think I gave a couple of reasons why this is not a good idea. Note that find does the same. It also takes the command as a sequence of arguments instead of a string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.