sharkdp / fd

A simple, fast and user-friendly alternative to 'find'
Apache License 2.0
33.83k stars 809 forks source link

`--abs-path` and `--rel-path` instead of `--full-path` #839

Open andreavaccari opened 3 years ago

andreavaccari commented 3 years ago

fd --full-path matches a pattern against the absolute path instead of the relative one. This is not well documented and it's a possible cause of confusion (e.g. #769). In my opinion, it is also less ergonomic than matching against the relative path of a candidate.

My suggestion is:

Thank you for the great work and for your focus on usability!

tmccombs commented 3 years ago

I like that idea. Though we would probably want to keep --full-path as a (probably hidden) alias for --abs-path for backwards compatibility.

andreavaccari commented 3 years ago

Thank you for taking this into consideration! It makes sense to maintain backward compat.

Separately, I realized there is --absolute-path to modify how results are printed but not how they are matched. Introducing --abs-path next to --absolute-path could itself cause confusion. One solution would be to rename the latter to --show-abs-path, which would align with --show-errors, but would break backward compat. Another solution would be to introduce the longer --match-abs-path and --match-rel-path.

sharkdp commented 3 years ago

fd --full-path matches a pattern against the absolute path instead of the relative one. This is not well documented and it's a possible cause of confusion (e.g. #769).

Thank you for your request. I am definitely in favor of improving the documentation. It should be clear that we match on the full absolute path.

In my opinion, it is also less ergonomic than matching against the relative path of a candidate.

Could you explain this in more detail? What is your use case and why is it unergonomic to solve it with --full-path?

andreavaccari commented 3 years ago

Could you explain this in more detail? What is your use case and why is it unergonomic to solve it with --full-path?

Say you have the following directory structure:

~
├── project/
│   ├── docs/
│   │   ├── some-doc.pdf
│   │   ├── some-doc.txt
│   │   └── secret.pdf
│   ├── repo/
│   │   ├── ...

Let's say I'm in project and I want to find all .pdf files in docs:

fd will only report results under the current working directory (or the argument passed), so most of the time I'd want to search against those. I do think there are cases where you might want to still match against the full path, but my intuition is that they'd be less common.

tmccombs commented 3 years ago

In that particular case, you could use

fd ".*\pdf$" docs
andreavaccari commented 3 years ago

That's fair, and I should have listed it as an option. However, I think the point remains valid. Your suggestion requires to "spread" my search between the <pattern>, which uses regex by default, and one or more <path>s, which can only use shell expansion. I believe it would be more ergonomic to to express the entire search in the <pattern>.

Separately, the original use case that motivated this issue was to find a set of files under my working directory, some of which must be at a specific location, while others could be anywhere within the working directory. In the example above, starting from project, how could I search exactly for ./docs/secret.pdf and for all .pdf files under repo with one command?

rafcamlet commented 3 years ago

I can provide another case, which was very confusing for me. Let's assume that I'm working on a repository and I want to find all files related to home subject, that means home is a part of the filename or part of the directory name containing files. On the first try, I would do something like: fd -p home , but that query will return basically every file in the repository, because the repository is in the user home directory /home/user_name/projects/my_repository. So the working solution would be fd -p "$(pwd).*home" and that's something I wouldn't expect. I've never had need to match against the whole absolute path, but against the relative one, very often, that's why I've always wondered why it's not even an option.

sharkdp commented 2 years ago

I'm sorry, but I find both use cases obscure enough to reject this feature request (please refer to the "majority of use cases" statement in the README). I will update the documentation though. Thank you very much for the discussion.

rafcamlet commented 2 years ago

Honestly, I'm surprised by this decision. And now I'm wondering if I use find-like tools differently than others ppl, because this absolute path approach is the most counterintuitive thing for me. This topic was raised at least three times in gh issues, and it always ended the same, so I have no other choice than just accept your decision and never bring it up again. Third time's a charm, as they say.

Thanks for your hard work. This tool is nearly perfect. 👍

sharkdp commented 2 years ago

Honestly, I'm surprised by this decision. And now I'm wondering if I use find-like tools differently than others ppl, because this absolute path approach is the most counterintuitive thing for me.

Did you see that I updated the documentation (21fd013)? Does this help, or do you still think it's confusing?

This topic was raised at least three times in gh issues, and it always ended the same

Could you please point to the other issues. I honestly cannot remember that this was discussed somewhere else. There have been questions about --full-path for sure, but did users really want --full-path to only search the displayed path? Or were they simply confused due to the inappropriate documentation?

so I have no other choice than just accept your decision and never bring it up again

Please don't. I'll reopen this for now.

rafcamlet commented 2 years ago

Did you see that I updated the documentation (21fd013)? Does this help, or do you still think it's confusing?

Yes, I saw it, and yes, it is helpful improvement. 👍

Could you please point to the other issues

https://github.com/sharkdp/fd/issues/306 https://github.com/sharkdp/fd/issues/609

There have been questions about --full-path for sure, but did users really want --full-path to only search the displayed path? Or were they simply confused due to the inappropriate documentation?

Both. :)

andreavaccari commented 2 years ago

Hi David, thank you for reopening the issue. Ultimately this is your project and it's your prerogative to decline requests. However, if you don't mind me asking for clarification, could you help me understand your mental mode for this? Here is mine.

When I search with fd, I model my usage like this: search in these directories for these criteria, and I image that the directories define the scope of the search, and the criteria define the filters within that scope. With this mental model, it makes life easier to expect directories and criteria to be orthogonal to each other.

In fact, I cannot think of a good example of when I'd want to match against the absolute path. If I had to pick only one of the two, I would favor relative paths to achieve the orthogonality mentioned above, but, assuming you have an equally reasonable mental model, supporting both options would support both mental models.

Andrius-B commented 2 years ago

I would also request the README to be changed to reflect this unintuitive behaviour. The current -p examples avoid this issue by using all-matching patterns for the beginnings of paths:

> fd -p -g '**/.git/config'
> fd -p '.*/lesson-\d+/[a-z]+.(jpg|png)'

I wish there was an example that shows how to use the absolute path functionality as rel-path e.g.:

> fd -p "$(pwd)/"'\w+/src/.*\.java'

on a side note, I think the > fd -p -g '**/.git/config' example would need the -HI flags, because the .git directory is not searched by default (though I might be mistaken)

sharkdp commented 2 years ago

With this mental model, it makes life easier to expect directories and criteria to be orthogonal to each other.

Exactly! But if you want directories and criteria to be orthogonal (which I assume to mean: independent), the search criteria themselves shouldn't be modified by changing the search path. This is what we achieve by always taking the absolute path.

Let's say I want to find files that contain foo in the path:

▶ mkdir foo; touch foo/bar                          
▶ fd --full-path --type=file foo
foo/bar

Now I would personally like to see the exact same search result, independent of what folder I'm currently in. This is why …

▶ cd foo     
▶ fd --full-path --type=file foo
bar

… also returns the bar file. If we would only search the relative path, the second search would have returned no results.

@andreavaccari what do you think? Did I interpret your "orthogonal" property incorrectly?


I just noticed that fd --full-path --type=file foo .. returns all files in the parent folder, presumably because the absolute search path is transformed into /tmp/foo/../ instead of /tmp. This is why every path matches the "foo" pattern. This should be fixed.

rafcamlet commented 2 years ago

Now I would personally like to see the exact same search result, independent of what folder I'm currently in.

So it's a matter of taste. For others, it's quite unnatural behaviour. Especially if you were find user. But it is not a request to change default behaviour, only for adding an option to alternate this mechanism, in order to have more ergonomic interface. Something like fd -P asdf instead of fd -p "$(pwd)/.*asdf"

I'm pretty sure that there are people who will use and appreciate such addition. https://github.com/manzaltu/modus-emacs/commit/dd6a1fe647eae27c8fb2d5bc785c0454cf2b80a9

andreavaccari commented 2 years ago

@sharkdp Yes you understood correctly what I meant with "orthogonal", and I now better understand your mental model. It seems we all agree that directories and criteria should be orthogonal/independent, but we disagree on what that means specifically. I think this difference stems from looking at the problem as the implementer of the program versus the user.

From an implementation standpoint, it's easier to collect all the files in the user-specified directories, then independently match their (absolute) paths against the user-specified criteria. From an usage standpoint, it's more natural to define the directories to search and then the criteria assuming "nothing exists outside those directories".

My points may not resonate with you but I do believe this thread has built a decent case for supporting this feature, especially considering that, as mentioned by @rafcamlet, it does not require a breaking change. Independent of your decision, thank you for building such a great tool!

benfleis commented 2 years ago

Hi @sharkdp, I agree on the intuition miss, and desire for absolute/relative path to be crystal clear. I just wrote a script that optionally used ** or subpath based on inputs for this structure. In this case, I expected b-dir to be a legit, more specific substitute for **:

@ben|  ~/a $ fd
b-dir
b-dir/file
c-dir
c-dir/file
@ben|X ~/a $ fd --full-path --glob '**/file'
b-dir/file
c-dir/file
@ben|  ~/a $ fd --full-path --glob 'b-dir/file'
@ben|  ~/a $

It's quite counterintuitive that the matching expression I specify does not work against the outputs I receive -- I expect them to be the same "kind". (Plus it's also my in-built intuition after years of find.)

jjjchens235 commented 2 years ago

+1 that relative path feature would be useful for my use-case(s) and that the current implementation is not as intuitive to me

minad commented 1 year ago

I also want to express my support for this feature. I maintain the popular Emacs package Consult, which provides various file search and grep utilities. There I've recently added the Fd-based command consult-fd after Fd gained support for the --and command line option. consult-fd allows you to enter multiple patterns to search for files name under the current project root directory, a little bit in the style of fzf. Right now consult-fd uses the --full-path option, such that the command is affected by unexpected matches of the path components of the project root directory - the problem described by @rafcamlet in https://github.com/sharkdp/fd/issues/839#issuecomment-912943336.

ChristianCiach commented 11 months ago

For the longest time I just assumed that -p -g is buggy, but I finally found this issue. Coming from find, this behaviour is a bit unexpected.

What I find even more unexpected is the fact that the printed results are using the relative paths of the found files. This seems strange. Why do I need to filter by absolute paths but are shown the relative results?

Norlock commented 4 months ago

Any progress on this? how do i search the relative path in full-path style?