fd icon indicating copy to clipboard operation
fd copied to clipboard

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

Open andreavaccari opened this issue 3 years ago • 21 comments

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:

  • Replace --full-path with --abs-path to make it clear this matches against the absolute path
  • Add a new flag --rel-path to allow matching against the relative path

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

andreavaccari avatar Aug 29 '21 23:08 andreavaccari

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

tmccombs avatar Aug 31 '21 04:08 tmccombs

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.

andreavaccari avatar Aug 31 '21 13:08 andreavaccari

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?

sharkdp avatar Sep 03 '21 05:09 sharkdp

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:

  • I could issue cd docs && fd ".*pdf$", but let's say I don't want to change directory.
  • Intuitively I'd want to issue fd --rel-path "^docs/.*pdf$"
  • Instead I'd have to issue fd --full-path ".*docs/.*pdf$" but this could also match docs dirs under repo.
  • Or I'd have to issue fd --full-path "$(cwd)/docs/.*pdf$" which works but seems unnecessarily convoluted.

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.

andreavaccari avatar Sep 03 '21 14:09 andreavaccari

In that particular case, you could use

fd ".*\pdf$" docs

tmccombs avatar Sep 03 '21 14:09 tmccombs

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?

andreavaccari avatar Sep 03 '21 15:09 andreavaccari

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.

rafcamlet avatar Sep 04 '21 09:09 rafcamlet

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.

sharkdp avatar Nov 14 '21 16:11 sharkdp

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. 👍

rafcamlet avatar Nov 14 '21 17:11 rafcamlet

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.

sharkdp avatar Nov 14 '21 18:11 sharkdp

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. :)

rafcamlet avatar Nov 14 '21 20:11 rafcamlet

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.

andreavaccari avatar Nov 15 '21 14:11 andreavaccari

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)

Andrius-B avatar Nov 16 '21 09:11 Andrius-B

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.

sharkdp avatar Nov 16 '21 19:11 sharkdp

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

rafcamlet avatar Nov 16 '21 22:11 rafcamlet

@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!

andreavaccari avatar Nov 16 '21 23:11 andreavaccari

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.)

benfleis avatar May 30 '22 10:05 benfleis

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

jjjchens235 avatar Sep 23 '22 21:09 jjjchens235

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.

minad avatar Sep 26 '23 08:09 minad

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?

ChristianCiach avatar Nov 01 '23 11:11 ChristianCiach