fd
fd copied to clipboard
`--abs-path` and `--rel-path` instead of `--full-path`
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!
I like that idea. Though we would probably want to keep --full-path
as a (probably hidden) alias for --abs-path
for backwards compatibility.
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
.
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
?
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 matchdocs
dirs underrepo
. - 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.
In that particular case, you could use
fd ".*\pdf$" docs
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?
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.
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.
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. 👍
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.
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. :)
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.
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)
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.
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
@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!
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
.)
+1 that relative path feature would be useful for my use-case(s) and that the current implementation is not as intuitive to me
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.
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?