fd: A simple, fast and user-friendly alternative to 'find'

718 tosh 293 3/19/2025, 11:44:17 AM github.com ↗

Comments (293)

snide · 13d ago
Big sharkdp fan. Ty you for making awesome software that i use DAILY.

bat, fd, hexyl, hyperfine

I'm going to take this moment to remind all of you well-paid engineers that if we each spread $10 a month sponsoring talented software makers like sharkdp the Internet would be a better place.

So many great little tools out there and we should try to support an ecosystem for them.

seafoamteal · 13d ago
bat, fd, and hyperfine are all by the same person??? That's incredible, I love all of these utilities.
jessekv · 12d ago
Seems like David Peter works at Astral now, as does Andrew Gallant (ripgrep).

It's a dream team for rust cli tools over there.

1-more · 12d ago
I owe hours of my life to Andrew Gallant aka BurntSushi's xsv. Nothing else tries to handle splitting long files into N-row chunks [1]. I was using the command line utility, but that's his wrapper around his rust-csv library. So if you need CSV parsing in rust, I strongly recommend this library.

[1] rows included linebreaks so your standard sed/head/tail/something-from-coreutils approach would not work.

singhrac · 12d ago
I have spent a lot of hours looking at `watch "xsv select ... | xsv table"`.
0cf8612b2e1e · 12d ago
Not that there is necessarily that much churn in csv processing, but last I looked, the xsv repo has not received much maintenance for a while.
chrishill89 · 12d ago
This is an active fork: https://github.com/dathere/qsv
_blk · 10d ago
Never realized it was a fork. qsv is great. I parsed lots of 4Gb files with it and was really happy.
wooptoo · 10d ago
There's also DSQ which uses SQL instead of its own language. https://github.com/multiprocessio/dsq
barotalomey · 12d ago
When software is feature complete, fast and working correctly, what is it exactly you expect to change?
0cf8612b2e1e · 12d ago
I mean there are 131 open issues and some 30+ PRs, so clearly people have some desire for change.

No criticism to the author. He is way more productive than I will ever be, but xsv does appear to be on the back burner. Open source means the author can spend their time how they like and I am entitled to nothing.

homarp · 1d ago
https://news.ycombinator.com/item?id=43494894 discusses xan https://github.com/medialab/xan

readme says this tool is originally a fork of BurntSushi's xsv, but has been nearly entirely rewritten at that point, to fit SciencesPo's médialab use-cases, rooted in web data collection and analysis geared towards social sciences (you might think CSV is outdated by now, but read our love letter to the format before judging too quickly). xan therefore goes beyond typical data manipulation and expose utilities related to lexicometry, graph theory and even scraping.

n8henrie · 12d ago
IIRC it was just deprecated in nixpkgs for this reason
paper2d · 6d ago
They are very good tools but I now prefer duckdb for CSV processing.
danso · 12d ago
Was just going to say, the fd,bat author reminds me of burntsushi (xsv, rg), in terms of the massive benefit they've added to the *nix command-line ecosystem.
tandr · 12d ago
Same Astral as `uv` makers? Geez, these guys are specializing on "making things go zoom-zoom"!
kiney · 12d ago
semi related: how does astral actually make money to pay the devs?
Narushia · 12d ago
Astral is primarily funded by venture capital firms. The head honcho, Charlie, has mentioned a few times that he’d like to develop and sell services that integrate well with Astral’s open-source tools. However, nothing concrete has been established or announced yet.
agumonkey · 12d ago
Man should write a tutorial on writing good utility software. Or teach even.
seanw444 · 12d ago
According to his website, he has:

https://shark.fish/rustlab2019

PaulDavisThe1st · 12d ago
I would not call that a tutorial on how to write good utility software. It's a quite specific description of how sub(1) was written, and it contains some useful lessons, but not many that would apply to the broad class of "utility software". I think.
agumonkey · 12d ago
ah well, he pwned me i just wasn't aware of it :)
gjvc · 12d ago
terminaltrove · 12d ago
in complete agreement, with tools like fd getting more visibility!

we sponsored fd's development a while back and we occasionally sponsor terminal tool authors from time to time at Terminal Trove where we have more tools in the trove. (0)

we're currently sponsoring zellij which I encourage you to check out and sponsor! (1)

https://terminaltrove.com/ (0)

https://github.com/zellij-org/zellij (1)

wanderingmind · 12d ago
Never knew about Terminal Trove.looks like an awesome place that collects a lot of useful terminal tools. This website must be a separate HN posting.
kstrauser · 12d ago
Hard agree about zellij. I used screen, then tmux, for years. Zellij feels "right" for me in a way those never quite did. It's brilliant.
aaplok · 12d ago
What differences between Zellij and tmux do you see as game changers?
kstrauser · 12d ago
It's like so many other projects we're talking about here: it has sane defaults. If you start Zellij for the first time, it shows you menus to do all the things you might want. A big plus is that it supports mouse scrolling by default, and the scrolling works 100% of the time as far as I can tell.

I don't know if it can do everything that tmux or screen can do. I bet it probably can't. But it does all the things I want such a thing to do, and without needing any configuration on my part.

aaplok · 12d ago
Interesting. When I tried Zellij I found that the menus were too much in my face, compared to tmux/screen more minimal design. I see how this is a good thing when you start using it but I wonder if it gets tiring in the long run, in a clippy sort of way.

But yes it makes sense that this feature makes it superior to tmux for some users. A good case for having diversity in software.

kstrauser · 11d ago
I could see that. I use Emacs with all the toolbars etc turned off. I get it.

I’m not a hardcore tmux user. I just like having persistent sessions on remote machines and bouncing between tabs, things like that. When I want to do something beyond that, with tmux I’d have to RTFM each time. In Zellij, the menu bar lets me discover it easily.

Bottom line: you’re right. I’m glad they both exist!

joshbaptiste · 10d ago
Only default of Zellij I can't stand is ctrl-q exits the whole instance
jhbadger · 12d ago
I'm glad you identified the author -- I'm a big fd and bat fan but didn't know they were created by the same person. I'll have to check out his other tools.
mgrandl · 12d ago
You should also check out numbat. It's insanely good.
stared · 12d ago
Link for anyone interested: https://github.com/sharkdp
numbers · 12d ago
I wish there was an easy way to find people to sponsor whose repos I use (not depend on because every project I use multiplies the same dependencies) but there are tools I use daily that aren't dependencies in my project like wezterm or atuin.
makapuf · 12d ago
Completely in line to put some money where my mind is regarding opensource (just sponsored framasoft from another thread).

Do keep in mind how much how trillonaire/billionaire companies sponsor the free software they use while doing so.

synergy20 · 12d ago
bat, fd, rg for me
alkh · 12d ago
Imo, everyone should check https://terminaltrove.com/ from time to time. There, I have found easy replacements to commonly used tools:

find -> fd, time(for runtime comparison) -> hyperfine, grep->ripgrep, asciinema + converting to .gif -> t-rec[1], manually creating convertional commits -> koji[2], etc.

[1]https://terminaltrove.com/t-rec/ [2]https://terminaltrove.com/koji/

johnisgood · 12d ago
koji would be fine, but I want to stick to 67 column width and I could not do it with this, I think? I use git-cola, instead.
alkh · 12d ago
yeah, that's a problem for me as well. I end up doing koji->gitlint->git commit --amend --edit if there are any width issues
tmtvl · 12d ago
Would be nice if you could filter based on license. I really want to avoid non-(A)GPL tools where possible.
imoreno · 12d ago
Instead of koji, I use `aider --commit`
enricozb · 12d ago
I wish fd and rg would align some of their flags. For example, both fd and rg have a --type, but for fd it means file/directory/symlink etc. For rg it means the file MIME type. Another example is that fd has an --extension flag, and rg doesn't.

Since I believe the correlation of usage of these tools is high, I think they could benefit from having similarly named flags.

hnlmorg · 12d ago
To be honest, this is one of the reasons I usually stick with POSIX tools, I’m too old and too lazy to want to learn a whole new set of flags for a whole new set of tools that are very close to but not quite the same as what’s already part of my muscle memory now.

Not taking anything away from the tools that have been written. Just for me, the pain of learning a new tool is greater than the convenience I’d gain from using it.

burntsushi · 12d ago
As the author of ripgrep, I find this unconvincing personally. Have you ever tried to use `sed` with its `-i` flag?

That's because `-i`, while incredibly useful, is not POSIX. So when you say "POSIX tools," what you actually probably mean is, "superset of POSIX tools."

There is some agreement among the same tools as what the options in the superset actually mean, but not always, as is the case with `sed`.

Compare, for example, what `man grep` says on your system with the POSIX definition: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/g...

As for whether flags are consistent across different tools, well that's a total crapshoot. `find` uses `-L` for following symlinks while `grep` uses `-R`. Ironically, both `fd` and ripgrep use `-L`, so they are more consistent than the relevant superset-plus-POSIX tooling on at least that front.

To be clear, I mean this somewhat narrowly. Namely

> I’m too old and too lazy

I totally get that. I have a bunch of things I kinda want to learn and do, but just not enough time in the day. But I do still try to make time for these things. I did it for `tmux` (previously, `screen`) and `zsh` (previously, `bash`) and I am very happy I did. Each one cost me about a Sunday and a half, but they've been paying rewards ever since.

hnlmorg · 12d ago
> As the author of ripgrep, I find this unconvincing personally. Have you ever tried to use `sed` with its `-i` flag?

I have. But that’s one inconsistency and an edge case I rarely need to worry about.

Plus we are talking about grep here, not sed. I created my own “sed” because I got fed up with dealing different implementations of existing seds. If others use it or don’t use it then that’s their choice, not mine.

> As for whether flags are consistent across different tools, well that's a total crapshoot. `find` uses `-L` for following symlinks while `grep` uses `-R`. Ironically, both `fd` and ripgrep use `-L`, so they are more consistent than the relevant superset-plus-POSIX tooling on at least that front.

UNIX tools are a mess too. My point wasn’t that their flags are more sane than modern tools. It’s that I’ve already committed to memory the flags for the tools I use daily.

> Each one cost me about a Sunday and a half, but they've been paying rewards ever since

I spend my free time writing open source tools that solve problems I run into (like fixing the limitations with existing UNIX shells, and presently writing a new terminal emulator with a ton of features existing ones neglect). So I don’t have time to learn new tools to solve problems I don’t have.

Edit:

I just want add to my previous comment that some of my open source tools do make use of your fantastic Go libraries, such as the Unicode width library.

So I’ve really valued your contributions to open source even though I don’t personally use ripgrep specifically.

burntsushi · 12d ago
I mean that seems pretty reasonable? I find your philosophy a little disappointing, but you do you. But it is reasonable. I think you ignored this part of my comment:

    > To be clear, I mean this somewhat narrowly. Namely
    >
    >> I’m too old and too lazy
    >
    > I totally get that.
jrockway · 12d ago
Yeah, I think your explanation is pretty reasonable. I am also old and lazy and still find time to try new tools.

I am not sure I have ever gotten traditional "find" to do what I want on the first try, and I've had a lot of first tries. At some point you have to ask yourself, if I haven't achieved zen in X years with Y tool, maybe the problem is the tool and not me?

alwillis · 12d ago
I’m old and lazy too, which is why I use eza, bat and other new tools that were created this century.

Why are we acting like we’re still in the 80’s and can only use tools that existed then?

hnlmorg · 12d ago
Not disappointing. Just pragmatic.

I have two young children plus maintain several open source projects (like yourself) and a full time job too.

Time isn’t infinite so I focus my energy on the stuff that makes the biggest impact.

It’s not like I’m ungrateful for your contributions to open source and if you’d look at some of the stuff I’ve been building you’d see we are pretty like minded with regards to modernising the command line.

burntsushi · 12d ago
Oh, no, definitely disappointing! At least to me it is. I totally believe in learning new things for the sake of it, because it sometimes leads to serendipitously good things. Otherwise it's really easy to end up in local optima. Without that philosophy, I would have never built ripgrep.

I'm not trying to convince you to do that. I already told you that your philosophy is reasonable. But I absolutely find it disappointing.

Anyway, yes, I have a kid. And all sorts of other things competing for my time. So I don't get much time to do serendipitous learning. But I try when I can. I cited two examples, but that's over a period of many years. I don't have time to do it often.

> you’d see we are pretty like minded with regards to modernising the command line

I bet we are. Maybe you are a lot more open to learning new things than you are letting on in your comments here. :-)

hnlmorg · 12d ago
If you’re willing to commit time to learning my shell then I’m willing to commit time to learning ripgrep. ;-)

https://murex.rocks

Edit:

> I bet we are. Maybe you are a lot more open to learning new things than you are letting on in your comments here.

Oh absolutely I’m open to learning new things.

Just recently I’ve been learning about tmux control mode (eg what iTerm2 uses for tmux integration) because I wanted to bypass tmux terminal emulation for specific escape codes, meaning I can then draw native elements inside a terminal window, such as spreadsheets, images, and code folding, while still having full tmux capabilities.

That was a “fun” ride. I plan on writing a blog about it at some point because there’s some features about tmux that I think others would be surprised to learn.

burntsushi · 12d ago
Oh man that's nowhere near fair! ripgrep is one tiny little command that is mostly compatible with GNU grep. Lots of the flags are the same. And its default usage is really easy: `rg whatever`.

But I gave it ten minutes and ported part of https://github.com/BurntSushi/dotfiles/blob/bedf3598f2501ad5... to https://github.com/BurntSushi/dotfiles/blob/bedf3598f2501ad5...

Not much, but it took me some time to get the basics down.

One thing that stood out to me was that startup times are kinda brutal. I'm not sure if that's intended or if it's something about my environment:

    $ cat /tmp/murex-test
    #!/usr/bin/murex

    echo $ARGV
    $ time /tmp/murex-test
    [
        "/usr/bin/murex",
        "/tmp/murex-test"
    ]

    real    0.437
    user    0.491
    sys     0.110
    maxmem  106 MB
    faults  0

    $ murex --version
    murex v6.4.2063 (develop)
    GPL v2
    2018-2025 Laurence Morgan
That would probably be a deal breaker for me.

I got murex through the AUR: https://aur.archlinux.org/packages/murex

> Oh absolutely I’m open to learning new things.

Okay then I'd say this is high contrast with your comments above!

hnlmorg · 12d ago
Yeah I’ve not spent time optimising start up because it’s main emphasis is the interactive shell.

I guess you could liken it to Powershell or JVM in that the start up is generally a one time cost if you’re using it interactively.

I could certainly invest a little time on the start up though. It wouldn’t be impossible to improve things there.

> Okay then I'd say this is high contrast with your comments above!

Is it though? I didn’t say I’m adverse to learning new things. Just that I don’t want to learn replacements for the tools I’ve already memorised.

But anyway, you’ve downloaded murex so I’ll give ripgrep go. I’m sure it’ll become a staple tool for me now I’ve committed time to it :)

burntsushi · 12d ago
Yeah I started with the shell script route because it felt like the best way to get familiar with it quickly. Then I'd probably go backwards to interactive usage.

The error messages did look very nice.

I have been considering dipping my toes into a less standard shell over the past few years. It is so so so hard to break away from the ubiquitous bullshit that most of us are stuck with. I have no love for the Bourne shell and its derivatives, although zsh is some nice lipstick on a very ugly pig.

The other candidates I'm aware of are fish, nushell and oils. I think nushell is the "most" different, but the last time I tried it, I bounced off of it for reasons I can't remember.

hnlmorg · 12d ago
Yeah, switching shell is a major time investment. I couldn’t blame you for sticking with the default, after all, I was initially unwilling to invest time into learning ripgrep :D

And you’re right that it wasn’t a fair a trade asking you to look at Murex in exchange for ripgrep (which is nice by the way!) but I respect that you did take a look nonetheless.

ziml77 · 12d ago
I’m happy you gave ripgrep an option to perform replacements so I don’t have to worry about sed and its lack of a standard way to change files in-place. I realize on my Mac I could install GNU sed, but if I’m going to install an extra utility anyway, why not go with something that is overall nicer?
burntsushi · 12d ago
Hah, well, hate to break it to you, but ripgrep never writes files, only reads them. So its `-r/--replace` option only controls ripgrep's output, but doesn't actually replace data inside a file.
ziml77 · 12d ago
I could swear I used it to do just that a handful of times in the past. But my brain's been a bit scrambled recently so I'm probably misremembering now. I know for sure I made use of the replace option and was happy it was there and that using it felt better than using sed.

I guess it does make sense now that I think about it that ripgrep wouldn't do in-place edits. If ripgrep never performs writes, there's never a chance of a mistake in usage or bug in the software clobbering files in bulk.

robenkleene · 12d ago
I maintain a pair of tools that can do in-place file replacements on ripgrep output (https://github.com/robenkleene/rep-grep) and rename files based on `fd` output (https://github.com/robenkleene/ren-find).
burntsushi · 12d ago
> If ripgrep never performs writes, there's never a chance of a mistake in usage or bug in the software clobbering files in bulk.

Yeah that's exactly why it doesn't.

It is true that the `-r/--replace` flag can replace a number of `sed` and `awk` use cases. It has for me at least.

thiht · 12d ago
sed has to be one of the worst POSIX tools. It sounds simple enough, but everytime I reach for sed it doesn't do what I want, either because it doesn't align with how I do things, or because it just doesn't support doing it (especially multiline replacements for example).

I've switched to sd[1] because it basically just works as I expect every time.

[1]: https://github.com/chmln/sd

ForTheKidz · 12d ago
ripgrep solves a really annoying part of the unix toolbox: inconsistency in how to correctly search a bunch of files for a string. Are you supposed to `find -name -exec`? Or are you supposed to `find -name | xargs -n 1`? Oh, but files can have spaces, so you might try `find -name -print0 | xargs`, but careful—`-print0` is not POSIX and you won't find it on some unixen! (let's not even discuss locate vs slocate vs mlocate.... ugh! Files are worse than everything but all the other options.)
sweeter · 12d ago
this is what tab completion and tldr is for. 99% of use cases are well covered and clear by the name of the flag, and a good CLI tool will make that easy to understand. A quick example and self-explanatory flags with tab-completion is all you need. Then if you ever have a more complicated use case, you can grep through the man page.

its legit as simple as "fd -e png -x optimize-png {}" the only thing I dont like about fd is that for some reason it kind of forces you to do 'fd . Downloads' if you just want everything in "Downloads" which equates to 'fd {pattern} Dir1 dir2" I wish you could omit the pattern sometimes.

renewiltord · 12d ago
It's actually because they stayed compatible that the problem arises: fd and find -type mean the same but this user wants them to be different.

Overall, I use AI shell completion so it's much smoother.

hnlmorg · 12d ago
I’ve been thinking of adding AI completion into my CLI tools but not really sure how to implement it in a non-intrusive way. So I’ve got a few questions, if you don’t mind sharing:

What’s the workflow like for AI shell completion?

How does it know which flag to complete for you? Do you write a description in native language (eg English) and it completes the entire command line? Or is it more one flag at a time?

renewiltord · 12d ago
Ah I do it from the other side

Got it from here

https://x.com/arjie/status/1575201117595926530?s=46

hnlmorg · 12d ago
Interesting. Thanks for sharing.

That gives me some ideas to try myself.

renewiltord · 12d ago
Good luck. Do share if any are sticky!
derriz · 12d ago
Yeah this annoys me even though I'm a daily user of both fd and rg. What makes it more confusing is that many of the flags DO align - or partially align.

For example, I'm used to glob patterns but the glob flag (-g) works differently in fd and rg. I think that fd's -g flag does not use "full-path" globbing while rg's -g does (or the other way around). To get fd to use rg style globs, it also needs the -p flag, which rg also recognizes but it has a completely different meaning for rg and has nothing to do with how globbing/filename matching works.

I guess I'm used to the warts at this stage, like I had gotten used to the warts on find and grep all those years ago.

Difficult or impossible to fix these inconsistencies at this stage without breaking backward compatibility.

thayne · 12d ago
It's a tricky balance. To use your --type example, it isn't consistent with rg, but it is mostly consistent with find. And fd'a --type option is much more useful for fd than an equivalent would be for rg. It doesn't make a lot of sense to filter the files to grep to directories, or sockets, but that is useful if you are searching for file names, or even just all files of a certain type. Conversely, rg's --type option isn't quite as useful for fd, because fd is already matching a pattern against the file name, so you can easily just add the appropriate extension to your search pattern. Or use the --exyension flag.
laktak · 12d ago
I used sql instead of flags to make it easier to remember - see https://github.com/laktak/zfind
terminaltrove · 12d ago
if you want to try fd, bat, numbat, hexyl and hyperfine, you can install them quickly and see screenshots of them below on Terminal Trove:

fd - https://terminaltrove.com/fd/

bat - https://terminaltrove.com/bat/

numbat - https://terminaltrove.com/numbat/

hyperfine - https://terminaltrove.com/hyperfine/

hexyl - https://terminaltrove.com/hexyl/

we make a real effort to ensure that you can install them with the ability to see the screenshots.

andy_xor_andrew · 12d ago
cool site, have you considered using asciicinema instead of screenshots? Seems like the perfect tool for what you're trying to do

https://asciinema.org/

archon810 · 9d ago
I clicked on several utils on the site, and they all had GIFs of the demos.

I think terminaltrove takes these from the projects themselves instead of creating them on their own.

nchmy · 11d ago
I look forward to exploring the tools some more. Though, I install everything these days via mise (which you list as well).

Would be cool if you had mise commands - be it just

mise use -g fd

or for other tools that arent in their registry, how to use the backends like

mise use -g cargo:xyztool

d0mine · 11d ago
Perhaps something like https://github.com/xtermjs/xterm.js can be used to show interactive sessions for TUI apps.
jwrallie · 12d ago
Nice suggestions, I’ll be definitely trying numbat and hyperfine (I already use fd daily).

I could see bat being useful only as the last program on a long pipe chain, but I really like xxd so I will pass on hexyl.

rednafi · 12d ago
One reason I haven’t picked up any of these newfangled Rust tools like bat, exa, or fd is that I can barely remember the options for the originals.

For me, anything that isn’t a drop-in replacement for the OG tools isn’t worth the friction. I use ripgrep inside VS Code but vanilla grep on the command line because of years of muscle memory.

That said, I don’t care what language a tool is written in as long as it works. One of my favorite Unix tools is GNU Stow, and it’s written in Perl. Even if these Rust tools were drop-in replacements, I probably wouldn’t bother installing them manually. As a user, the speed improvements and memory safety don’t really matter to me.

There are other languages, like Go, where memory safety is guaranteed as well, and Go’s performance is more than adequate for tooling—with the added benefit of getting more engagement from the community. So I’m not entirely convinced by this “Rust is the savior” narrative.

That said, if macOS or Ubuntu decided to hot-swap the OG tools with Rust alternatives that behave exactly like their predecessors, I probably wouldn’t complain—as long as it doesn’t disrupt my workflow.

jhbadger · 12d ago
>One reason I haven’t picked up any of these newfangled Rust tools like bat, exa, or fd is that I can barely remember the options for the originals.

But that's exactly the reason to use the newer tools -- they just make more sense -- especially fd over find. I've been using UNIX for over thirty years and find just never clicked with me.

TylerE · 12d ago
Confession; the only way I’ve ever actually used find is just a tree walker piping to grep to actually find whatever.

No comments yet

quinncom · 12d ago
fd is probably better for most tasks, but sometimes it seems more cumbersome than find. E.g., to delete all files inside a cache directory, this is the simplest syntax I could find:

fd -t f -X rm {} \; ^ cache

Which makes me really nervous, so usually I fall back to using find:

find cache -type f -delete

Maybe this is foolproof for me only because I’ve been using find for decades. Is there a version of this for fd that inspires more confidence?

orlp · 12d ago
I would suggest

    fd -t f . cache -X rm --
Which reads as find "any file", "matching .", "in directory cache", then "execute rm -- followed by an argument list of all found files".

This ensures even if you have filenames starting with - they won't be interpreted as options for rm. For even more sanity of mind you may want to turn on -a for absolute paths, although I don't see an example right now where using relative paths would go wrong.

quinncom · 11d ago
Yes, that looks safer. I didn't realize I could put the `-X` option at the end. The man page says:

Usage: fd [OPTIONS] [pattern] [path]...

So, I presumed the path had to go last.

whompyjaw · 12d ago
It absolutely does not matter what language this tool is written in. That goes for any tool. If it’s better, use it. In this case, fd is far superior to “find” in almost every way. Sane defaults, wayyy faster, easy options (just use cht.sh if you can’t remember) To me, there is no reason to ever use “find”. If I’m on a new system, I just install fd and carry on.
syklemil · 12d ago
> It absolutely does not matter what language this tool is written in. That goes for any tool.

Eh, there are a lot of tools where it actually does kind of matter. I suspect for a lot of invocations of tools like `fd` and `rg`, they'll be done before an equivalent written in java has even had its JVM spin fully up.

There's _tons_ of Java software, but it somehow never managed to make a dent in the CLI space.

> To me, there is no reason to ever use “find”. If I’m on a new system, I just install fd and carry on.

I guess I should finally have a look at how to replace my `find $path -name "*.$ext" -exec nvim {} +` habit … turns out it's `fd -e $ext -X "nvim" "" $path`

graynk · 11d ago
it tangentially matters, because cargo is so good that I use it instead of a package manager for all these fancy rust tools
eulers_secret · 12d ago
Another reason to at least learn the default tooling is that often I find myself SSHing to another machine which has only the barest of default packages installed (often busybox, sometimes just a stripped-down docker container).

If I didn't know how to use "find" and "grep" (though I prefer rg) then I'd be at a disadvantage in these situations. Also command-line git.

It's why I learned to use Vim well, though I daily Emacs.

thesuperbigfrog · 12d ago
>> For me, anything that isn’t a drop-in replacement for the OG tools isn’t worth the friction.

"The uutils project reimplements ubiquitous command line utilities in Rust. Our goal is to modernize the utils, while retaining full compatibility with the existing utilities. We are planning to replace all essential Linux tools."

https://uutils.github.io/

uutils is being adopted in Ubuntu 25.10:

https://www.theregister.com/2025/03/19/ubuntu_2510_rust/

rednafi · 12d ago
I welcome this wholeheartedly. If Ubuntu adopts that and it doesn’t need me to deal with any incompatibility, then it’s a win-win for everyone.
d0mine · 11d ago
Does it mean unless your ip is considered “friendly“, you can’t use basic computer utils? Gnu utils seem more accessible (more freedom long term).
consp · 12d ago
With the added "benefit" of not having to use GPL. Likely the main goal.
thayne · 12d ago
Why would that matter to Ubuntu?
BeetleB · 12d ago
If you're already proficient with grep, find, etc - there's not much reason to switch. As I said elsewhere:

I never managed to use find because I always had to look up command line arguments. I would always find a different way to solve my problem (e.g. Midnight Commander).

I use fd all the time.

A better interface makes a big difference.

thayne · 12d ago
> there's not much reason to switch

There are a few reasons you might still want to switch. In fd'a case:

- It respects .gitignore files (as well as similar .fdignore files that aren't git specific), which can help you find what you care about without a lot of noise, or having to pass a lot of exclude rules to find

- it can search in parallel, which can significantly reduce latency when searching large directories.

However, there are also reasons you might want to keep using find:

- fd can't do everything find can. fd is intended to replace the most common use cases with a simpler interface, but there are many less common cases that require finds greater flexibility. In fact, I still use find sometimes because of this.

- find is more likely to already be installed

theragra · 10d ago
By the way, FAR manager was ported to Linux quite a long time ago, but I forgot about it.

Recently I remembered and installed it. Not too hard to install (although you need to use third party repos sometimes).

And then - voila - a lot of convenience for dinosaurs from Norton Commander era like myself, who cant remember cli tools syntax that well.

BeetleB · 10d ago
I use FAR on Windows. Midnight Commander serves me well in Linux - not sure I'd prefer FAR manager. But yes, FAR is closer to Norton than mc.
theragra · 10d ago
Far has many nice plugins and features, that's why I prefer it. MC is still awesome, sure.
johnisgood · 12d ago
> One of my favorite Unix tools is GNU Stow

What about https://zolk3ri.name/cgit/zpkg/? A lot of improvements have been done behind the scenes apparently (rollback, proper states, atomicity, etc.), but I am not sure when he is willing to publish.

I personally use it as-is when I am compiling stuff myself and the ZPG_DST is ~/.local/. It works well for keeping track of programs that I compile and build myself.

nrvn · 11d ago
It resonates with me wrt muscle memory and ubiquity of “standard tools” that come pre-installed in majority of *nix distros including macos.

But there is a big BUT! Lately I have to use grep/find huge nested dirs and found rg to be an order of magnitude faster. Had to get myself comfortable with retraining the muscle memory. Worth the effort.

Some of these new shiny tools are meh for my taste. Delta for instance. Or helix the editor. But it is personal. Overall I love the competition. It seems like industry once full of innovators and tinkerers is lacking some shake up.

mellosouls · 12d ago
For anything I can't remember, I just use at the command line:

? toolname <option>

Eg

? git branch

which gives me common examples of git branch

It aliases to tldr which is normally up to date with new tools.

See also cheat.sh etc.

https://tldr.sh/

I understand the point about muscle memory but I think that was more of a concern in the days before we had it easy with instant internet answers and now LLMs (eg GitHub copilot command line) doing our boring thinking for us.

actinium226 · 12d ago
Is anyone else bothered by the fact that by default it ignores a lot of folders? I use `find` when I'm like 'I just want to know where on my system this is, wherever it might be'

I know fd has options to not ignore things, but I can never remember them, so I just go back to find because I know it'll search everything.

pantsforbirds · 12d ago
I actually prefer it. It's very similar to ripgrep's default search. I do occasionally want to find something in a .gitignore, or other hidden directory, but I don't mind taking the time to `rg/fd --help` and add the flag to include hidden directories.
jandrese · 12d ago
Same thing that drives me crazy with Windows built-in file search. The Windows one ignores AppData, which is where everything gets stashed these days.
Joe_Cool · 12d ago
I completely dumped the windows search and only use voidtool's Everything when I am on a Windows box.

It can search multiple indexed NTFS drives in miliseconds. Indexing is usually a few seconds since it works directly on the NTFS structures. (and it integrates with Total Commander)

ajolly · 12d ago
You should check out void tools search everything!
eredengrin · 12d ago
Same, this is why I haven't fully converted to lots of these newer tools. If I have to remember a bunch of special flags to make them look at the files I need them to, their advantage is lost. I'm better off using the originals and solidifying those flags in my muscle memory since at least those tools will be on any system I use. I do use ripgrep on occasion but not very often.
burntsushi · 12d ago
ripgrep has the same default behavior.

You just want `fd -u`. Or in ripgrep's case, `rg -uuu`.

`fd`, I believe, got `-u` from ripgrep. And I can say that ripgrep got its `-u` from `ag`.

kstrauser · 12d ago
That’s a feature, and one of the reasons I prefer it. When I want to find a file in a git repo, say, there’s no need looking inside .git most of the time. Sometimes there is: if I don’t remember `fd -u`, there’s good old find there for me. But that’s almost never what I want to do, so fd’s defaults are sensible for me.

No comments yet

jpeeler · 12d ago
Same, I never remember them either. However, I use a shell (fish) that has decent command history autocompletion that helps a lot for such things.

I wish the flags between ripgrep and fd lined up as I think that's what confuses me (can't remember now haha).

travisgriggs · 12d ago
I’ll have to try this out. I admit that most of my uses of find looke like

find . | grep what_i_am_looking_for

Because I can never remember how finds arguments work. I like the integrated xargs like behavior as well.

One thing I did not see in there was how fd handles symlink directory traversal? Searched the whole readme for it, and only found options to match on symlinks or not.

timewizard · 12d ago
You're just using the unix pipeline as it was intended. I always prefer this over having to remember a bunch of obscure command line switches.
VTimofeenko · 12d ago
Check out `curl cht.sh/${utility_name}`. It will print a short help page with some common examples
hnlmorg · 12d ago
Shameless plug:

Or just press F1 if you use my shell.

https://murex.rocks/user-guide/interactive-shell.html#autoco...

helsinki · 12d ago
Hm, I feel like I have roughly the exact same functionality with zsh and some various plugins, including the meta editing experience shown in your demo video ($EDITOR) via Kitty and/or WezTerm.
hnlmorg · 12d ago
With some effort it’s possible to bend zsh to any workflow, but there’s a lot to be said for having sane defaults.

The other value add for alternative shells like my own is better support in the language for handling structured data (is not treat everything as a dumb byte stream).

Ultimately though, productivity is all about familiarity and if you’re also super efficient in zsh then I’m not going to try and convince you that some shiny new tool is better.

moozilla · 12d ago
Which plugins are you using? I've been looking to upgrade my zsh experience so some suggestions would be helpful.
bee_rider · 12d ago
I’m finding that I use locate more and more for this sort of thing. Of course, it produces a lot more output, because it looks at the whole system. But, it is still much faster than find because it runs on some kind of index or something, and it is easy enough to grep out the directory I’m interested in, if needed.
gcmeplz · 12d ago
locate is nice, but I think that on most distros its index is only updated once/day (unless you adjust the cron job that updates it more often). Most of the times I'm trying to find something, I haven't modified it recently, but it can definitely lead you astray.
silisili · 12d ago
One can just run 'sudo updatedb' to refresh it. Super fast if it's already on a schedule. I think mine is set to update every system update, so I just have a habit of running that before I use locate each time.
diziet_sma · 12d ago

  fd --help | rg link -C 10
Set -L --follow to descend into symlinked directories. The default is to not.
layer8 · 12d ago
In that case, you might as well just use grep -r, or its alias rgrep. And then remember that it supports --include=GLOB, --exclude=GLOB, and --exclude-dir=GLOB.

(That’s GNU Grep, just to be clear: https://www.gnu.org/software/grep/manual/grep.html#File-and-...)

yread · 12d ago
Err no? grep searches contents and op is looking in filenames
forinti · 12d ago
Not the same thing, but thank you. I've been using "find . -type f -exec grep -i {} /dev/null \;" without looking for a better solution and here it is.
ltbarcly3 · 12d ago
nope, not remotely the same thing
xiphias2 · 12d ago
That's basically rg
jorams · 12d ago
No, rg looks inside files. find . | grep just lists all files and directories and then filters it down using grep.
dietr1ch · 12d ago
You may want `fd | fzf` or fzy instead. That way you can filter and select interactively
kjkjadksj · 12d ago
Why pipe to grep instead of applying the pattern in the find command?
pimlottc · 12d ago
> Because I can never remember how finds arguments work
kjkjadksj · 6d ago
Man find?
kstrauser · 12d ago
I use the heck out of fd daily and it’s in my standard installation on new machines. I’ve used find for years and it’s great in its own ways, but convenient ergonomics isn’t among them.

I’m 100% on board with this recent-ish trend toward new replacement utilities that may or may not retain all of the flexibility of the originals but are vastly easier to use for common cases.

agumonkey · 12d ago
As much as i love new rust cli tools, `fd` ended up in the same bag as tar and ln.. I can never retain how to use it. I don't blame anybody .. I'm just witness that I always have to re-read the man from scratch to get anything done. And I'm not a gnu find lover.. with all its idiosyncracies.. somehow it registers better.
nottorp · 12d ago
> As much as i love new rust cli tools

Why would you love them just because they're in rust?

I'd like to praise the author of this fd for not having "Rust" all over the web page or in the HN link, actually.

The Rust inquisition would get far less pushback if instead of threatening people that god will kill a kitten every time you use a non-kosher programming language, they'd promote software that improves (even opinionated improves, like this fd) on existing tools instead of having its main feature "but it's written in Rust!".

stouset · 12d ago
That is literally what people are doing. “Written in Rust” has become a pretty convenient shorthand for “this was written by someone who cares deeply about quality, and you can guess that it will be extremely fast, relatively free of bugs, and use as many cores as you want to throw at it”.

While you’re out here complaining, the Rust community has built a truly impressive array of improved, human-focused command line tools (rg, bat, fd, hyperfine, delta, eza, and on and on) and a bunch of best-in-class libraries for building tools (regex comes to mind).

BoingBoomTschak · 12d ago
While mostly true, there's a large problem with lots of these Rust CLI tools (and I use some of them, don't misunderstand me): they often discard the UNIX philosophy in favour of newbie friendliness and glitter.

For example, ripgrep shouldn't merge find and grep (actually, I use a personal wrapper around `find ... -exec grep ... {} +` because my only beef with this is that find's syntax to exclude stuff is horrible, https://git.sr.ht/~q3cpma/scripts/tree/master/item/find_grep). Or you see something like https://github.com/shssoichiro/oxipng/issues/629 because people don't even know how to use xargs...

Feels like if someone did a RIIR on ImageMagick, it'd be able to talk with Instagram and Flickr by itself or process RAW files like Darktable. Would probably have some kind of tagging system too.

burntsushi · 12d ago
I used a similar wrapper for years before I wrote ripgrep. But now all of those wrappers are gone because ripgrep covers all of their use cases (and then some). I'm not a newb and I don't really care about glitter. So I don't know where you're getting your condescension from personally.

GNU grep discards the Unix philosophy in all sorts of places too. Like, why does it even bother with a -r flag in the first place? Did people back then not know how to use xargs either? I mean, POSIX knew not to include it[1], so what gives?

What's actually happening here is that what matters is the user experience, and the Unix philosophy is a means, not an end, to improve the user experience. It's a heuristic. A rule of thumb to enable composition. But it doesn't replace good judgment. Sometimes you want a little more Unix and sometimes you want a little less.

Besides, you can drop ripgrep into a shell pipeline just like you would grep. All that Unix-y goodness is still there.

[1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/g...

BoingBoomTschak · 12d ago
> GNU grep discards the Unix philosophy in all sorts of places too.

Who ever claimed that GNU was a proponent of the UNIX philosophy? Certainly not me.

> What's actually happening here is that what matters is the user experience, and the Unix philosophy is a means, not an end, to improve the user experience

Yes and no. The expression "user experience" implies that all users are the same and benefit from the same philosophy of software interface design.

> Besides, you can drop ripgrep into a shell pipeline just like you would grep. All that Unix-y goodness is still there.

The "Unix-y goodness" isn't only defined by what it can do, but also what it can't do. I don't want to turn this into a suckless rant, so I won't. Also, not having a mode giving it POSIX grep compatibility really flies in the face of that claim: I want my scripts to work on BSD, MacOS and even Solaris/AIX without having to install stuff.

------

I know I may sound very smug but believe me when I say that I really like some of these utils and the care put into them (and I know you're the author of ripgrep) and that I'm no UNIX OpenBSD user (Plan 9 exists for a reason, and I favor CL over C/Go any time of the day). But I really see them as optimizing for/targeting the VSCode/Zed crowd, instead of the vim/emacs one, if you know what I mean.

stouset · 12d ago
> Who ever claimed that GNU was a proponent of the UNIX philosophy? Certainly not me.

Nothing was specific to GNU in that comment. `-r` is available in BSD grep too. You are being needlessly pedantic and avoiding the actual points being made while doing so.

> Yes and no. The expression "user experience" implies that all users are the same and benefit from the same philosophy of software interface design.

No, it doesn’t. You have literally made that up out of whole cloth, but it isn’t how anyone else I’m aware of defines “user experience”.

As BurntSushi pointed out, ripgrep is even designed to adapt to different means of use: as a standalone command, as a utility in a pipe, and others. Improving the usability for one use-case isn’t necessarily at the cost of others.

> I want my scripts to work on BSD, MacOS and even Solaris/AIX without having to install stuff.

So your very reasonable desire to stick with POSIX for shell scripts… means we shouldn’t ever make new tools? I’m genuinely failing to understand your point here.

In fact, having a “grep compatibility flag” would very literally be the opposite of the UNIX philosophy you’re holding up elsewhere. ripgrep isn’t grep. It isn’t trying to be grep. It’s something new and different and (in some use-cases) better. The old thing still exists and if you want to use it for whatever reason… just do that?

BoingBoomTschak · 12d ago
> Nothing was specific to GNU in that comment. `-r` is available in BSD grep too. You are being needlessly pedantic and avoiding the actual points being made while doing so.

Where's the actual point in "others do it too"?

> No, it doesn’t. You have literally made that up out of whole cloth, but it isn’t how anyone else I’m aware of defines “user experience”.

That's not a question of definition, but of use in an English sentence. If you say "this is good for user experience", you implicitly group all users together. I say some users prefer tools that do only one thing. ripgrep itself acknowledges that "despite initially not wanting to add every feature under the sun to ripgrep, over time, ripgrep has grown support for most features found in other file searching tools". And that's fine! But not for everybody.

> As BurntSushi pointed out, ripgrep is even designed to adapt to different means of use: as a standalone command, as a utility in a pipe, and others. Improving the usability for one use-case isn’t necessarily at the cost of others.

If I like the "finding files with auto filtering" part of ripgrep, how can I use it to feed another grep or even another tool? If it had been designed with the aforementioned philosophy, it would have been "ripfind" + "ripgrep" and maybe a "ripfg" pretty interface on top.

> So your very reasonable desire to stick with POSIX for shell scripts… means we shouldn’t ever make new tools? I’m genuinely failing to understand your point here.

> In fact, having a “grep compatibility flag” would very literally be the opposite of the UNIX philosophy you’re holding up

See my other reply: I love new tools, but "UNIX-like goodness" is also about portability (as in SUS), not just the philosophy. More of a misunderstanding than anything else, really.

A flag would be impossible, but introspection based on argv[0] (like Busybox) wouldn't be that far-fetched. But yeah, clearly ripgrep isn't trying to replace only grep, that was a mistake on my part.

As an addendum, the "UNIX philosophy" had a lot of crap parts (e.g. bytes as universal interchange format) and UNIX itself is a very poor implementation of said philosophy (after all, g/re/p itself is pointless porcelain over (s)ed, heh), I'm not sure discussing it seriously without specifying which part (like "do one thing") is very productive.

burntsushi · 12d ago
> If I like the "finding files with auto filtering" part of ripgrep, how can I use it to feed another grep or even another tool?

`rg --files`

Is your mind blown yet?

> is also about portability

Except for Windows.

BoingBoomTschak · 12d ago
Happy this was thought out! Still everything in one tool, but glad modularity was truly considered.

> Except for Windows.

Of course POSIX portability doesn't apply to OSes which intentionally ignore it. I think I have another flame appreciating guy on the other side of the conversation =)

burntsushi · 12d ago
It just means that your claims about portability are, in the real world, far less useful than is imagined. I ship software to Windows users and the "portability" of POSIX doesn't help there. Doesn't matter why to me. It just means that I can't depend on POSIX for the "portability" benefits that its proponents seem to cite so enthusiastically.
umanwizard · 12d ago
> But I really see them as optimizing for/targeting the VSCode/Zed crowd, instead of the vim/emacs one, if you know what I mean.

At this point it sounds like you're making a purely aesthetic/cultural judgment, rather than a technical one. ripgrep works just fine with emacs; I have "C-c p s r" bound to "run ripgrep in current project" and use it almost every day.

burntsushi · 12d ago
OK, so you phrased your criticism very narrowly toward "lots of these Rust CLI tools," but in actuality, your criticism applies way more broadly than that. Likely to just about all of GNU's tooling, for example. And probably BSD's and busybox's tooling too. Even busybox isn't above implementing POSIX+some, and AFAIK none of them provide a strict "POSIX only" mode.

Which is fine, but now your position is more "old man yelling at clouds" than it is something specific about the Rust tools. (And to be clear, I'm not above yelling at clouds now and then.)

> Also, not having a mode giving it POSIX grep compatibility really flies in the face of that claim

No... it doesn't? ripgrep being compatible with the Unix philosophy is not the same as it being POSIX compatible. I didn't say you could use ripgrep in any place you could use grep in a drop-in compatible way. I said you could use it in shell pipelines. As in, it inter-operates with other tooling in a Unix-y way.

And besides, I don't know of any grep that has such a mode. How do you know you aren't using a grep flag that isn't available in other grep implementations?

> But I really see them as optimizing for/targeting the VSCode/Zed crowd, instead of the vim/emacs one, if you know what I mean.

Nope, I don't. I've been a vim (now neovim) user for decades. And neovim even uses ripgrep by default over grep if it's installed.

BoingBoomTschak · 12d ago
> OK, so you phrased your criticism very narrowly toward "lots of these Rust CLI tools," but in actuality, your criticism applies way more broadly than that.

Obviously. The topic was Rust CLI tools, that's why my post focused on them. Indeed, my criticism is broader.

> Likely to just about all of GNU's tooling, for example. And probably BSD's and busybox's tooling too. Even busybox isn't above implementing POSIX+some, and AFAIK none of them provide a strict "POSIX only" mode.

This isn't about POSIX or not POSIX, this is about introducing yet another pure convenience feature for something that can easily be achieved with other accompanying (guaranteed to be on the concerned platform) tools. POSIX doesn't create features anyway, it's about describing things that have already become standard; the Austin Group bug tracker is quite explicit about this.

> No... it doesn't? ripgrep being compatible with the Unix philosophy is not the same as it being POSIX compatible.

Well, just a question of interpretation of "Unix-like goodness". UNIX is both a philosophy and a portability standard (since POSIX == SUSv4). And as I said, doing one thing and doing it well is another facet of that philosophy; finding files != searching in them.

> And besides, I don't know of any grep that has such a mode. How do you know you aren't using a grep flag that isn't available in other grep implementations?

Compatibility != strict rejection of anything else, quite obviously.

> Nope, I don't. I've been a vim (now neovim) user for decades. And neovim even uses ripgrep by default over grep if it's installed.

Which is why I said vim instead of neovim (even if neovim is clearly better).

------

I think you misunderstand my position because I like a bit of snark: compromising on the "do one thing" part of the UNIX philosophy isn't necessarily something horrible, but it's not an imaginary issue either. I could give other examples (like how the pretty clean xsv became https://github.com/dathere/qsv) but it really doesn't matter because I think it's more of a popular CLI "apps" thing than Rust alone, even if there's community overlap.

burntsushi · 12d ago
I can no longer see any coherent point you're trying to make.

My point is that you are treating an ideal ("do one thing and doing it well") as an end instead of a means. Moreover, you are treating it as if there is any actual choice in the matter. In reality, the tooling most of us use on the command line violates the Unix philosophy in some way or another. So the question is not "should I adhere to the Unix philosophy?" but "what makes a good user experience?"

BoingBoomTschak · 12d ago
I don't see why my point is that hard to see: the "do one thing" part of the UNIX philosophy is a good ideal to aim for, even if often ignored in favour of a more convenient kitchen sink approach. I then just mentioned that a good majority of these useful Rust tools (I really like hyperfine and oxipng, for example) don't seem to care much about it.

Some example of that idea I use every day is https://codemadness.org/sfeed-simple-feed-parser.html, where feed parsing, serialization and visualization are completely separated in small orthogonal binaries with very few options. It could have been one fat "sfeed" or something like its newsboat instead. (shilling it a bit more there: https://world-playground-deceit.net/blog/2024/10/sfeed-setup...)

sgarland · 11d ago
I’ve also been guilty of insisting on this, even when, as you point out, most tooling doesn’t strictly follow it anyway. I think it’s an overreaction from being irritated at seeing app after app fall to “now including AI,” or just pivoting for new features because it wasn’t making money fast enough.

FWIW, I’ve been using *nix for about 25 years, and had zero problems adapting to ripgrep. You kept -i and -v, which honestly covers 90% of common usage.

bbkane · 12d ago
I personally appreciate the newbie friendliness and glitter, and even the "make the common case easier at the expense of composability" tradoff, though I think tlmost of these tools are still relatively composable.
alwillis · 12d ago
When I setup a new machine, the first two apps I install are bat and eza.

Both are “must haves” as far as I’m concerned.

dietr1ch · 12d ago
The ecosystem enables focusing on the task at hand. It's great that you don't need to get side-tracked at every single step. There's many high quality libraries.
thiht · 12d ago
> Why would you love them just because they're in rust?

That's not it. People love the new rust tools because they're great tools with sane defaults. They happen to be written in Rust most of the time and that's it so people use this to describe them.

chrisweekly · 12d ago
That's a bit extreme. I'm not who you replied to, but IME, things written in rust tend to be fast and sane. All else equal, "written in rust" is a positive signal to me.
agumonkey · 12d ago
performance for a start

especially in the case of fd, it's way faster than gnu find

sorry if that annoys people, but a rust tool starts with a high trust in my mind that it will fly

ps: to show i'm not in full fanboy mode, i'm often surprised that fzf, brilliant and performant tool, is written in go, but i know it's not rust :)

alp1n3_eth · 12d ago
Surprisingly, Go is great for CLI tooling. It may not have the insane speed that carefully planned and written Rust does, but it's very easy to write and be performant without even needing to go to great lengths to optimize it.

I generally say that anything under 500ms is good for commands that aren't crunching data, and even Python CLI tools can come in under that number without too much effort.

bbkane · 12d ago
Unfortunately, Python CLI startup time is correlated with how many files the interpreter has to interpret, which usually takes effort to combat, so larger CLIs that have a lot of functionality and thus files always seem to slow down.

The Azure CLI is a good example of this. It's been a year or two since I used it, so maybe it's improved since then, but it used to take a second or two just to run `az --help`, which infuriated me.

If you own a slow Python CLI, look into lazily importing libraries instead of unconditionally importing at the top of each Python file. I've seen that help a lot for slow Python CLIs at $DAYJOB

nottorp · 12d ago
> especially in the case of fd, it's way faster than gnu find

... also the only tool written in Rust that made it to HN lately that does not scream "I'm written in Rust!" everywhere :)

It also aims to improve on gnu find, not to reimplement it because it's in a non approved language.

It's what the Rust evangelists aren't.

bee_rider · 12d ago
For tar, I just remember tar czvf and tar xzvf.

Of course, then we get the question, ok, why not use a program that just provides those options? But, I think all the extra functionality of tar is nice to have sitting off there in the background; I’d have to look it up if I actually wanted to use it, but it is all there in the documentation, and nicely compatible with the files produced by my memorized commands.

sitkack · 12d ago
Fully laden Gnu tar or BSD tar?
bee_rider · 12d ago
I guess GNU most likely. On my system, it’s just Ubuntu, and on the server side, it is, I guess, whatever the administrator installed, haha.
kiwijamo · 12d ago
Both commands work in either I believe. I've been using both since my FreeBSD days and now I use Debian Linux with no change.
mitsu_at · 12d ago
Reminded of this xkcd :P https://xkcd.com/1168/
umanwizard · 12d ago
If you’re having trouble remembering the order of arguments to ln, remember that it’s the same way around as cp. Worked for me.

That is, if before there is something at /some/path but not /another/path , after running

  ln /some/path /another/path
there will be something there (same as cp).
stouset · 12d ago
The one that always trips me up is that `ln` is “dumb” about how it handles the first argument.

If the first argument isn’t an absolute path, it must be relative to the second argument, and not to pwd.

    ln ./foo ./bar/baz
./bar/baz will be a symlink whose literal contents are `./foo` so it will look for foo in the same directory (bar), rather than in bar’s parent directory.

This is totally backwards from how other utilities behave. Which is completely understandable if you know what it’s doing under the hood. But it is counterintuitive and surprising.

tavianator · 12d ago
At least with GNU coreutils, you can use `-r`/`--relative`
stouset · 12d ago
TIL!
bbkane · 12d ago
I've never internalized this, so I usually stick to using absolute paths...

Not a solution for all problems, but it works for me most of the time.

stouset · 12d ago
Absolute paths will break if, for example, the target and source are in the same directory but you move the directory.

Sometimes you semantically want absolute paths (I want to symlink a thing to /bin/foo), sometimes you want relative paths (I want to symlink a thing to something in a nested directory).

mturmon · 12d ago
This is what made the “ln” argument order click for me as well.

Another piece of this parallel is that (with cp and mv) you can omit naming the destination file - you often just name the directory:

  cp /other/dir/foo.txt .
The corresponding shortcut with ln is not naming the destination at all, and the symlink is created in the working directory:

  ln -s /other/dir/foo.txt
Both of the above are my most common usage patterns, and the abbreviation of the second argument in both helps reinforce the parallel between cp, mv and ln.
agumonkey · 12d ago
thanks, i still need to ignore the fact that the link on the right points to the left then
porridgeraisin · 12d ago
> tar

I remember only two flags for tar. That's it.

  tar -x
  tar -c
c for create, x for extract.

I use it like so:

  tar -c src | gzip > src.tar.gz
and extracting like

  curl https://source.code/src.tar.gz | gunzip | tar -x
That's all.

The core operations taking up only this much headspace leaves the door open to slowly start to retain all its other useful options. For example, -v, which means verbose almost everywhere, thankfully means verbose here too, so I add that when I want verbosity.

Similarly, I find it easy to retain -l which lists the contents. I do this quite often for stuff from the internet -- I don't like it when I untargz in ~/Downloads and it untargz's it in the same directory instead of doing everything inside a parent directory (preferably with the same name as the archive)

Bonus: separating out the gzip like this makes it easy to remember how to use zstd if you want to, just pipe to zstd instead! "Unix philosophy" and all that.

I agree with you about `ln`, I can never seem to remember if it's source or target that comes first.

pimlottc · 12d ago
For folks on macOS, you can also use "mdfind" as a command-line interface for macOS Spotlight search

https://ss64.com/mac/mdfind.html

spudlyo · 12d ago
Considering how many as many CPU cycles and iops that Spotlight robs from you on a regular basis, you might as well get some use out of it.
kstrauser · 12d ago
I never remember what it's called, so I have `alias locate 'mdfind -name'` in my shell setup.
pimlottc · 12d ago
If it helps you remember, it appears that the "md" in "mdfind" stands for "metadata" [0]

0: https://en.wikipedia.org/wiki/Spotlight_(Apple)#macOS

kstrauser · 12d ago
Yeah, for some reason my brain's incapable of pinning that in cache.

Oh well, that's what they invented aliases for in the first place.

ilyagr · 12d ago
I got used to https://github.com/tavianator/bfs instead. Breath-first ordering is nice.

Interestingly, the author is listed as one of the maintainers of `fd` as well.

meisel · 12d ago
Personally I prefer bfs (https://github.com/tavianator/bfs) because it does a breadth-first search
tavianator · 12d ago
Someday I will get that functionality into fd :)
meisel · 12d ago
Looking forward to it!
kiitos · 11d ago

    COMMAND                                 OUTPUT    WALLCLOCK_SEC     USR_SEC    SYS_SEC
    time find ~ -iregex '.*\.jpg$' | wc -l  14372             45.04        4.59      13.23
    time find ~ -iregex '.*\.jpg$' | wc -l  14372             48.42        4.60      13.59
    time find ~ -iname '*.jpg' | wc -l      14372             44.55        1.07      13.57
    time find ~ -iname '*.jpg' | wc -l      14372             44.94        1.08      13.64
    time fd '.*\.jpg$' ~ | wc -l            14325              4.01        2.67      24.16
    time fd '.*\.jpg$' ~ | wc -l            14325              4.37        2.73      30.28
    time fd -g '*.jpg' ~ | wc -l            14325              3.98        2.72      25.84
    time fd -g '*.jpg' ~ | wc -l            14325              4.04        2.69      26.82
Good to use concurrency, predictable impact on all of the various timings. Different results vs. find for the same term (assumedly) are unexpected? Did I mess up the translations?
Babkock · 12d ago
One of those essential tools, that's not ever included with GNU/Linux by default, but I always install almost immediately along with ripgrep, bat, fzf, htop.
kristopolous · 12d ago
try ugrep https://github.com/Genivia/ugrep ... if you don't switch over in a day, I'll eat my shoe.

It supports all the common grep options and you can split view in the -Q mode and it is smart enough to open your $editor at the line number it's talking about.

Try it, this is the workflow I've been waiting for.

Also lf. https://github.com/gokcehan/lf You've been wanting this for years as well.

No really. Just scroll: https://github.com/gokcehan/lf/wiki/Integrations ... https://github.com/chmouel/zsh-select-with-lf these things will change your life. I promise.

Babkock · 12h ago
I didn't know about these!
ac29 · 12d ago
> Also lf. https://github.com/gokcehan/lf You've been wanting this for years as well.

Check out yazi, its the nicest TUI file manager I have used: https://yazi-rs.github.io/

kristopolous · 4d ago
https://github.com/sxyazi/yazi looks way more legit than the website. Not everyone who writes good software knows how to sell it ;-)
kstrauser · 12d ago
Whoa! Thankgs for mentioning lf. That's beautiful!
amelius · 12d ago
I'm on bash, and now I'm jealous :(

By the way, this reminds me of the Norton Commander days ...

kristopolous · 12d ago
bash bind and zsh bindkey are similar enough that you can probably just llm convert it to bash.

curl https://raw.githubusercontent.com/chmouel/zsh-select-with-lf... | llm -x "Convert this zsh script to bash" > maybe-bash.sh

seems to work for me.

kstrauser · 12d ago
I'm on Fish and the integrations don't work as-is for me either. However, the tool itself is quite slick!
creeble · 12d ago
For the sake of Ubuntu users, it’s ‘apt install fd-find’. You’ll need an alias fd=fdfind too.
meonkeys · 12d ago
Agreed! Curious what your base OS is. Mine has been Ubuntu LTS for years, but now I find myself installing so many custom tools like these I'm thinking I might want to move to NixOS or Gentoo or something like that instead. I just don't want to lose out on stability and great hardware support.
carlhjerpe · 12d ago
Hey!

I would recommend trying home-manager, or just plain nix profiles before going all-in on NixOS, it's very easy to add Nix on top of any Linux (and MacOS to an extent).

This way you still have your tried and true base system and you can manage things somewhat like you're used to (and use venv and whatever bullshit package manager everyone invents), a lot of common tools will work poorly on NixOS (venv, npm...)and while they have Nix alternatives that are "better" it's DIFFERENT.

I run NixOS on desktop and laptop but I wouldn't recommend starting with it, you can benefit from all packages on any distro by just installing Nix.

Also home-manager adoption can be incremental.

ADHD end note: home-manager is perfect for CLI tools installation and config. You must unconfigure "secure path" in sudo though otherwise your CLI tools don't work with sudo

thibran · 12d ago
I would add 'ouch' to the list. It allows easy compression/de-compression.
drcongo · 12d ago
Tomte · 12d ago
> fd is distributed under the terms of both the MIT License and the Apache License 2.0.

So not dual-licensed (MIT OR Apache-2.0), but MIT AND Apache-2.0? That's unusual.

Later: it seems they intended dual-licensing, and botched the wording: https://github.com/sharkdp/fd/issues/105

greggh · 12d ago
Every new install gets zsh, kitty, exa, fzf, bat, ripgrep, fd, neovim, ducker, qman, cht.sh, navi, and hyperfine as the first things I do.
metaltyphoon · 12d ago
zsh, fzf, bat, rg, fd, neovim, tldr, lazygit, jq, yazi, starship, hyperfine, ghostty.
helsinki · 12d ago
Now we're talking.
nout · 12d ago
My favorite way is to just have this in my zsh aliases.

  # Find file by prefix (ignore case). 
  # Usage: 'f' or 'f myfile' or 'f myfile.txt \etc' 
  # or f '*css'

  function f() {
    find ${2:-.} -iname "${1}*" 2>/dev/null | grep '^\|[^/]*$'
  }

  # We use noglob, so zsh doesn't expand characters like "*" 
  # and so we can do e.g. f *css
  alias f='noglob f'
sandos · 12d ago
Yeah, I was trying the -exec functionality of find just yesterday, something which Iv'e done many times before, but that was long ago.

I eventually gave up! Thats how ergonomic find is :)

mrobot · 12d ago
Has anyone made an awk replacement? I find awk get's really annoying and ugly really fast, as things become even mildly complicated.

I feel like awk could be so much better.

TylerE · 12d ago
For me anything beyond the most trivial one liner I just write in python or whatever.

Maintainability >>>>>>> terseness.

It's not 1976 where every cycle matters.

luckman212 · 12d ago
I just released an Alfred workflow[0] for searching a group of user-defined directories, that heavily relies on fd under the hood. Thank you @sharkdp for this amazing tool, I use it every day and it is wonderful.

Hyperfine is another underrated gem that is just so great.

[0] https://github.com/luckman212/alfred-pathfind/

usrbinbash · 12d ago
There are many completely unnecessary "reworks" of classic UNIX stdutils that add very little to no value, and instead pitch themselves purely on "written in {lang-the-dev-likes}" or being "blazing fast" or something similar.

`fd` isn't one of those.

`fd` is amazing.

It is simpler, faster and easier to grok than `find`, the commands syntax is a straight up improvement, it comes with sane defaults which makes the easy things and common usecases simple, while the harder ones are way more accessible. It uses colored output in an actually useful way, its manpage is more structured and easier to read...

and MOST IMPORTANTLY

...it is capable of running commands on search results with parallel execution out of the box, so no need to get GNU parallel into the command.

THIS is the kind of renewal of classic command line utilitis we need!

Literally the only pain point for me, is that it doesn't use glob-patterns by default, and that is easily fixed by a handy

    alias gf="fd -g"
beej71 · 12d ago
This is an honest question, not a criticism, but how much does parallelism help? Isn't the disk a choke point?
usrbinbash · 11d ago
Theoretically yes, practically not really (any more). NVMe cards are fast enough that a single core traversing the file system can actually be a chokepoint, so parallelisation helps a lot here.

I also should have made it clear that my comment also wasn't so much about the search (although the parallel search is absolutely a nice-to-have)...it was about the `-x, --exec` being automatically in parallel.

A common usecase is to find all files of X criteria, and then perform the same operation on all of them, e.g. find all session logs older than N days and then compress them, or convert all wav files in a directory tree to mp3

If the operation is computationally expensive, using more than one core speeds things up considerably. With `find`, the way to do that was by piping the output to GNU parallel.

With `fd` I can just use `-x, --exec` and it automatically spins up threads to handle the operations, unless instructed not to.

kstrauser · 12d ago
Depends greatly on the use case. If you're finding all the gifs in a directory and converting them to pngs, it may be the case that CPU is hammered harder than IO. There are surely counterexamples, too.

It's a nice option to have when you need it.

swiftcoder · 12d ago
A lot of developer machines are running expensive NVME SSDs, which perform well enough the disk isn't so much of a choke point. If you run on spinning rust, YMMV
linza · 12d ago
I find these tools super awesome, but i never use them beyond trying them out once, because they don't usually come with coreutils or something like that.

Haven't found a way to use these tools in a user-local way.

For my own homemade tools, i put the binary in my dotfiles and they end up in .local/bin and i can use them by default. I can do that because I don't need to update them.

singhrac · 12d ago
I use fd all the time. I admit it, I couldn't get the muscle memory right for find. One day I'll be on a bare Linux installation where I can't cargo install whatever I want and I'll have to ask ChatGPT to generate my find commands.

I like `fd -o {user}` and `fd --newer {time}` to find recently changed files and owned by others.

keithnz · 12d ago
On windows, for those that don't know, use Everything from https://www.voidtools.com/

This is a VERY fast file searching tool. It's crazy good.

HeadlessChild · 12d ago
This saved me a ton of time when I had to migrate id ownership of files in ancient NFS shares.

[0] https://news.ycombinator.com/item?id=31489004

anacrolix · 12d ago
I like it but the defaults are super annoying. I'm always trying to find things I can't otherwise but it defaults to ignoring git dirs and dot files, literally the thing I search for the most
theflyinghorse · 12d ago
After using nushell for a few month it's really hard for me to go back to the old ways. A million of different tools all with different API and outputs are just not the way to go
BeetleB · 12d ago
I never managed to use find. I would always find a different way to solve my problem (e.g. Midnight Commander).

I use fd all the time.

Simply having a better command line interface is a big deal.

puffybuf · 12d ago
fzf, ripgrep are some command line tools I like. Check them out. Being able to quickly search your history with fuzzy finder is so useful.
tucnak · 13d ago

    alias fd="rg --files | rg"
GCUMstlyHarmls · 12d ago
This isn't directly comparable, `fd` will find files with `X` in the name, but the `rg` alias will find all paths with `X` in it.

Eg,

    λ mkdir wing && touch wing/xwing.exe wing/tie.exe

    λ fd wing
    wing/
    wing/xwing.exe

    λ rg --files | rg wing
    wing/tie.exe
    wing/xwing.exe
tucnak · 12d ago
I guess you're right. Isn't the former more useful in general? I find myself reaching for `:Rg` in Vim much more often than `:Files` or `:GFiles` courtesy of fzf.
DaSHacka · 12d ago
They're just completely different tools.

The other day I was searching for a PDF I downloaded three years ago from a certain company.

Simply ran `find ~/Downloads -iname '<company-name>'` and it immediately popped up.

rg would not have helped me there. Even if I used something like rga, it would have taken significantly longer to parse the contents of every file in my home directory.

oguz-ismail · 13d ago

    $ touch $'a.\xFF'
    $ find -name $'*.\xFF'
    ./a.?
    $ ./fd -e $'\xFF'
    error: invalid UTF-8 was detected in one or more arguments

    Usage: fd [OPTIONS] [pattern] [path]...

    For more information, try '--help'.
    $
    $ touch III
    $ LC_ALL=tr_TR.UTF-8 find -iname 'iii'
    $ LC_ALL=tr_TR.UTF-8 ./fd 'iii'
    III
    $
Every fucking time
packetlost · 13d ago
Ok, but like, in practice this is a pretty weird edge case. It's impractical and usually worthless to have filenames that can't be described using the characters on a keyboard.
bravetraveler · 12d ago
Disagree, filesystems provide for both services and people... this is an imposition. I, a mere human, may need my tools to wrangle output generated by other software that has never once used a keyboard. Or a sensible character/set, bytes are bytes

File extensions - or their names - mean absolutely nothing with ELF. Maybe $APPLICATION decides to use the filename to store non-ASCII/Unicode parity data... because it was developed in a closet with infinite funding. Who knows. Who's to say.

Contrived, yes, but practical. Imposing isn't. The filesystem may contain more than this can handle.

packetlost · 12d ago
My point is that it's such a weird edge case in the first place that the chances of you needing to use a tool like fd/find in this way is vanishingly small. I agree with the general issue of treating file paths as encoded strings when they are not. Go is the worst offender here because it does it at the language level which is just egregious.

Regardless, the point is moot because `fd` handles the filenames gracefully you just need to use a different flag [0].

[0]: https://news.ycombinator.com/item?id=43412190

bravetraveler · 12d ago
No more unusual than using "find" at all, is my point.
xorcist · 12d ago
Not at all. It's a common result of the resulting Mojibake (https://en.wikipedia.org/wiki/Mojibake) after moving files between platforms.

It's also what made Python 3 very impractical when it orginally came around. It wasn't fixed until several versions in despite being a common complaint among actual users.

Galanwe · 12d ago
Which keyboard ?
packetlost · 12d ago
Any of them. File names are in the vast majority of cases human readable in some character encoding, even UTF-8. You would be hard pressed to find a keyboard/character code that has characters that aren't represented in Unicode, but it doesn't matter, just honor the system locale.
ivanjermakov · 13d ago
I think it's common for tools to assume that file names are valid unicode, not surprized.
SAI_Peregrinus · 12d ago
Common, but rather stupid. Filenames aren't even text. `fd` is written in Rust, and it uses std::path for paths, the regex pattern defaults to matching text. That said, it is possible by turning off the Unicode flag. `(?-u:\x??)` where `??` is a raw byte in hex. E.g. `(?-u:\xFF)` for OP. See "Opt out of Unicode support[1] in the regex docs.

[1] https://docs.rs/regex/latest/regex/#opt-out-of-unicode-suppo...

jcranmer · 12d ago
IMHO, the kernel should have filesystem mount options to just reject path names that are non-UTF-8, and distros should default to those when creating new filesystems on new systems.

For >99.99% of usecases, file paths are textual data, and people do expect to view them as text. And it's high time that kernels should start enforcing that they act as text, because it constitutes a security vulnerability for a good deal of software while providing exceedingly low value.

xorcist · 12d ago
So just turn off support for external media, which could possibly be created on other platforms, and all old file systems? Legacy platforms, like modern Windows which still uses UCS-2 (or some half broken variant thereof)?

While I support the UTF-8 everywhere movement with every fiber of my body, that still sounds like a hard sell for all vintage computer enthusiasts, embedded developers, and anyone else, really.

jcranmer · 12d ago
As I said in another comment, you can handle the legacy systems by giving a mount option that transcodes filenames using Latin-1. (Choosing Latin-1 because it's a trivial mapping that doesn't require lookup tables). UCS-2 is easily handled by WTF-8 (i.e., don't treat an encoded unpaired surrogate as an error).

The reality is that non-UTF-8 filenames already break most modern software, and it's probably more useful for the few people who need to care about it to figure out how to make their workflows work in a UTF-8-only filename world rather than demanding that everybody else has to fix their software to handle a case where there kind of isn't a fix in the first place.

burntsushi · 12d ago
What is text? Are the contents of files text? How does one determine if something is text?

(I'm the author of ripgrep, and this is my way of gently suggesting that "filenames aren't even text" isn't an especially useful model.)

SAI_Peregrinus · 12d ago
Oh, I agree that "text" isn't well-defined. The best I can come up with is that "text" is a valid sequence of bytes when interpreted in some text encoding. I think that something designed to search filenames should clearly document how to search for all valid filenames in its help or manual, not require looking up the docs of a dependency. Filenames are paths, which are weird on every platform. 99% of the time you can search paths using some sort of text encoding, but IMO it should be pointed out in the man page that non-unicode filenames can actually be searched for. `fd`'s man page just links to the regex crate docs, it doesn't generate a new man page for those & name that.

As for "filenames aren't even text" not being a useful model, to me text is a `&str` or `String` or `OsString`, filenames are a `Path` or `PathBuf`. We have different types for paths & strings because they represent different things, and have different valid contents. All I mean by that is the types are different, and the types you use for text shouldn't be the same as the types you use for paths.

burntsushi · 12d ago
I'd suggest engaging with this question, which I think you ignored:

> Are the contents of files text?

It is perhaps the most prescient of all. What is the OS interface for files? Does it tell you, "This is a UTF-8 encoded text file containing short human readable lines"? No, it does not. All you get is bytes, and if you're lucky, you can maybe infer something about the extension of the file's path (but this is only a convention).

How do you turn bytes into a `&str`? Do you think ripgrep converts an entire file to `&str` before searching it? Does ripgrep even do UTF-8 validation at all? No no no, it does not.

I'd suggest giving https://burntsushi.net/bstr/#motivation-based-on-concepts and the crate docs of https://docs.rs/bstr/latest/bstr/ a read.

To be clear, there is no perfect answer here. You've got to do the best with what you've got. But the model I work with is, "treat file contents and file paths as text until you heuristically believe otherwise." But I work on Unix CLI tooling that needs to be fast. For most people, I would say, "validate file contents and file paths as text" is the right model to start with.

> but IMO it should be pointed out in the man page

Docs can always be improved, sure, but that is not what I'm trying to engage with you about. :-)

SAI_Peregrinus · 12d ago
I'd say some files are text, some are not. And I agree that there's no good way to tell! I think ripgrep has a much harder job than fd, because at least fd can always know that all paths it's searching are valid paths for the OS in use.
burntsushi · 12d ago
My point is that you can apply to the answer to the question "are the contents of files text?" to the question "are file paths text?"
SAI_Peregrinus · 12d ago
I get it. I think you're right that they both have the same problem, but paths have a std type for handling them that, while file content's don't. As long as you're on an OS you can use std::path::Path (or PathBuf) for paths, and ensure they're valid. I suppose I should have said "Paths aren't Strings" or similar, they might be text but they might not be, and fundamentally the issue is that they're different data types. "Text" isn't universally defined.
burntsushi · 12d ago
You can't really just use `std::path::Path` though. Because it's largely opaque. How do you run a regex or a glob on a `std::path::Path`? Doing a UTF-8 check first is expensive at ripgrep's scale. So it just gets it to `&[u8]` as quickly as it can and treats it as if it were text. (These days you can use `OsStr::as_encoded_bytes`.)

`std::path::Path` isn't necessarily a better design. I mean, on some days, I like it. On other days, I wonder if it was a mistake because it creates so much ceremony. And in many of those cases, the ceremony is totally unwarranted.

And I'm saying this as someone who has been adjudicating Rust's standard library API since Rust 1.0.

jakeogh · 12d ago
Tools must be general. Im not going to invest time using a new one if it cant handle arb vaild filesystems. But thats just me.

https://github.com/jakeogh/angryfiles

burntsushi · 12d ago
`fd` does, as pointed out in this thread in numerous places. So I don't know what your point is, and you didn't engage at all with my prompt.
149765 · 13d ago
Had to lookup regex crate docs, but it's possible:

    $ fd '(?-u:\xFF)'
    a.�
coldpie · 13d ago
Can you elaborate on what's going on here? Something like "fd" is assuming your filenames are UTF-8, but you're actually using some other encoding?
burntsushi · 13d ago
What's happening here is that fd's `-e/--extension` flag requires that its parameter value be valid UTF-8. The only case where this doesn't work is if you want to filter by a file path whose extension is not valid UTF-8. Needless to say, I can't ever think of a case where you'd really want to do this.

But if you do, fd still supports it. You just can't use the `-e/--extension` convenience:

    $ touch $'a.\xFF'
    $ fd '.*\.(?-u:\xFF)'
    a.�
That is, `fd` requires that the regex patterns you give it be valid UTF-8, but that doesn't mean the patterns themselves are limited to only matching valid UTF-8. You can disable Unicode mode and match raw bytes via escape sequences (that's what `(?-u:\xFF)` is doing).

So as a matter of fact, the sibling comments get the analysis wrong here. `fd` doesn't assume all of its file paths are valid UTF-8. As demonstrated above, it handles non-UTF-8 paths just fine. But some conveniences, like specifying a file extension, do require valid UTF-8.

kccqzy · 13d ago
Right because file names are not guaranteed to be UTF-8. That's the reason Rust has str and then OsStr. You may assume Rust str is valid UTF-8 (unless you have unsafe code tricking it) but you may not assume OsStr is valid UTF-8.

Here an invalid UTF-8 is passed via command line arguments. If it is desired to support this, the correct way is to use args_os https://doc.rust-lang.org/beta/std/env/fn.args_os.html which gives an iterator that yields OsString.

SAI_Peregrinus · 12d ago
No, OsStr is for OSes that don't encode strings as UTF-8, e.g. Windows by default. Use Path or PathBuf for paths, they're not strings. Pretty much every OS has either some valid strings that aren't valid paths (e.g. the filename `CON` on Windows is a valid string but not valid in a path), some valid paths that aren't valid strings (e.g. UNIX allows any byte other than 0x00 in paths, and any byte other than 0x00 or `/` in filenames, with no restrictions to any text encoding), or both.
oguz-ismail · 13d ago
fd is assuming the argument to -e is valid UTF-8 while filenames can contain any byte but NUL and /
porridgeraisin · 13d ago
"I cook up impractical situations and then blame my tools for it"

Nobody cares that valid filenames are anything except the null byte and /. Tell me one valid usecase for a non-UTF8 filename.

coldpie · 12d ago
UTF-8 is common now, but it hasn't always been. Wanting support for other encoding schemes is a valid ask (though, I think the OP was needlessly rude about it).
porridgeraisin · 12d ago
It's backwards compatible with ascii right?

But yeah I suppose you would need support for all the other foreign-language encodings that came in between -- UCS-2 for example.

But basically nobody does that. Glib (which drives all GTK apps' and various other apps file reading) doesn't support anything other than UTF8 filenames. At that point I'd consider the "migration" done and dusted.

coldpie · 12d ago
The world is a lot more complicated & varied than you think :) I was digging around in some hard drives from 2004 just last weekend. At that time, lots of different encodings were common, especially internationally. Software archaelogy is a common hobby, it could be nice to be able to use a tool like this to search through old filesystems. "Not worth the effort" is definitely a valid response to the feature request, but that also doesn't mean there is absolutely no use for the feature.
jcranmer · 12d ago
I can definitely see a use case for supporting non-UTF-8 pathnames on disk (primarily for archaeological purposes).

In a UTF-8-path-only world, what I would do is have a mount option that says that the pathnames on disk are Latin-1 (so that \xff is mapped to U+00FF in UTF-8, which I'm too lazy to work its exact binary representation right now), and let the people doing archaeology on that write their own tools to remap the resulting mojibake pathnames into more readable ones. Not the cleanest solution, but there are ways to support non-UTF-8 disks even with UTF-8-only pathnames.

porridgeraisin · 12d ago
Oh yeah I can imagine the pain for drives from that era. I remember reading that sometimes you need the right "codebook" - what was the word - installed and stuff like that.
creeble · 12d ago
You do not have (or write programs for) filesystems that contain loads of ancient mp3 and wma files.

It is the bane of my existence, but many programs support all the Latin-1 and other file name encodings that are incompatible with UTF-8, so users expect _your_ programs to work too.

Now if you want me to actually _display_ them all correctly, tough turds...

porridgeraisin · 12d ago
True. Btw curious, is there a defined encoding for text in mp3 metadata? Or is that a pain too.
shakna · 12d ago
Running a shell script went badly, generating a bunch of invalid files containing random data in their names, rather than one file containing random data.

You wish to find and delete them all, now that they've turned your home directory into a monstrosity.

dleink · 12d ago
nah, eff all that. Roll back the snapshot.
dspillett · 12d ago
It isn't wrong, 0xff is invalid UTF8. Of course if your locale is not set to UTF8 then that is a potential problem.
vsl · 12d ago
*nix filenames are series of bytes, not UTF-8 (or anything else) strings. If a find replacement doesn't accept valid (parts of) filenames as input, it's a bit unfortunate.
coldpie · 12d ago
If all you want to do is match against a sequence of bytes, sure. But when you want to start providing features like case-insensitivity, matching against file extensions, globbing, etc, then you have to declare what a given byte sequence actually represents, and that requires an encoding.
oguz-ismail · 12d ago
> when you want to start providing features like case-insensitivity

fd does that for English only. See the III/iii case in my comment; iii capitalizes to İİİ in Turkish, there's no way to have fd respect that.

burntsushi · 12d ago
> fd does that for English only.

That's false. Counter-example:

    $ touch 'Δ'
    $ fd δ
    Δ
Your Turkish example doesn't work with `fd` because `fd` doesn't support specific locales or locale specific tailoring for case insensitive matching. It only supports what Unicode calls "simple case folding." It works for things far beyond English, as demonstrated above, but definitely misses some cases specific to particular locales.
jandrese · 12d ago
Casefolding is a minefield once you extend past English. It is completely unsurprising to find problems with it in other languages.
burntsushi · 12d ago
Yes. I'm the one who implemented the case folding the `fd` uses (via its regex engine).

See: https://github.com/rust-lang/regex/blob/master/UNICODE.md#rl...

And then Unicode itself for more discussion on the topic: https://unicode.org/reports/tr18/#Simple_Loose_Matches

TR18 used to have a Level 3[1] with the kind of locale-specific custom tailoring support found in GNU's implementation of POSIX locales, but it was so fraught that it was retracted completely some years ago.

[1]: https://unicode.org/reports/tr18/#Tailored_Support

DrNosferatu · 12d ago
No flatpak / snap for latest version and automated upgrades?
foresto · 12d ago
fd is also a file & directory maintenance command by Shirai Takashi. (Package name: fdclone) I think it has been around for at least couple of decades.
coldtea · 12d ago
Amazing program. Along with rg great QOL improvements
grenran · 12d ago
annoyingly fd also stands for file descriptor
chinabot · 11d ago
Works really well for me. tks
zie · 12d ago
I honestly never use find anymore, I just use ripgrep(rg). rg is so fast, that I don't worry about the ridiculously extra overhead of searching content. I can't remember the last time I used find.
derefr · 12d ago
I was just thinking yesterday that I'd appreciate a more modern alternative to find(1). Not a simplified one, though!

The original problem that led me to thinking about this, was that I wanted to do a search that would include all files below the current directory, except if they were within a specific subdirectory.

(Why not just `grep -v` for that directory? Because the subdir contained millions of files — in part, I was trying to avoid the time it would take find(1) just to do all the system calls required to list the directory!)

And yes, this is possible to specify in find(1). But no, it's not ergonomic:

    find . -path ./excluded_dir -prune -o -type f -print
You can add parentheses, if you like. (But you don't have to. It seems find(1) has implicit Pratt parsing going on):

    find . \( -path ./excluded_dir -prune \) -o \( -type f -print \)
This incantation entirely changed my perspective on find(1) as a tool. Until I learned this, I had never understood exactly why find(1) nags you to put its arguments in a specific order.

But this makes "what find(1) does under the covers" very clear: it's assembling your expression into a little program that it executes in the context of each dirent it encounters on its depth-first traversal. This program has filtering instructions, like `-path`, and side-effect instructions, like `-print`. You can chain as many of each as you like, and nest them arbitrarily within (implicit or explicit) logical operators.

After some further experimentation, I learned that find's programs are expression-based; that every expression implicitly evaluates to either true or false; and that any false return-value anywhere in a sub-expression, is short-circuiting for the rest of that sub-expression. (You could think of every instruction as being chained together with an implicit &&.) This means that this won't print anything:

    find . -false -print
In other words, my original expression above:

    find . -path ./excluded_dir -prune -o -type f -print
...is actually this, when translated to a C-like syntax:

    (path("./excluded_dir") && prune()) || (type("f") && print())
As soon as I realized this, I suddenly became very annoyed with find(1)'s actual syntax. Why is find(1) demanding that I write in this weird syntax with leading dashes, various backslash-escaped brackets, etc? Why can't I "script" find(1) on the command-line, the same way I'd "script" Ruby or Perl on the command-line? Or heck, given that this whole thing is an expression — why not Lisp?

    find '(or (and (path "./excluded_dir") prune) (and (type f) print))'
I do understand why find(1) was designed the way it was — it's to allow for shell variable interpolation, and to rely on shell argument tokenization.

But it's pretty easy to work around this need — just push both of these concerns "to the edge" (i.e. outside the expression itself. Like SQL statement binding!)

• Support $VAR syntax for plain references to exported env-vars.

• Support positional binding syntax (?1 ?2 ?3) for positional arguments passed after the script.

• Support named binding syntax (?foo) for positional arguments after the script that match the pattern of a variable-assignment (ala make(1) arguments):

    find '(or (and (path ?excluded_dir) prune) (and (type f) (iname ?1) print))' foo excluded_dir="${bar[1]}"
I don't know about you, but I personally find this grammar 10x easier to remember than what find(1) itself has going on.
tavianator · 12d ago
You might be interested in rawhide[1] or fselect[2]. (Note: I don't really use them myself, but they seem to offer something like what you're suggesting.)

Also, this is still a find-style syntax, but my bfs utility supports -exclude [3]. So you can write

    bfs -type f -exclude -path ./excluded_dir
which is a bit more ergonomic.

[1]: https://github.com/raforg/rawhide

[2]: https://github.com/jhspetersson/fselect

[3]: https://github.com/tavianator/bfs/blob/main/docs/USAGE.md#-e...