
A common mistake involving wildcards and the find command - robertelder
https://blog.robertelder.org/find-command-wildcard-globbing/
======
svnpenn
As another user mentioned, many POSIX and/or GNU utilities havent aged well. I
respect trying to stay portable, but peoples needs change over time and these
tools simply havent kept up. Like the other user, I use Fd now instead:

[https://github.com/sharkdp/fd](https://github.com/sharkdp/fd)

As well as Silver Searcher:

[https://github.com/ggreer/the_silver_searcher](https://github.com/ggreer/the_silver_searcher)

while Grep performance is pretty good, its also gotten pretty stale with
regard to its defaults and options.

~~~
anonsivalley652
For grepping, rg is faster and saner.

[https://github.com/BurntSushi/ripgrep](https://github.com/BurntSushi/ripgrep)

On end-user systems with fast I/O, it is usually a better use of resources to
have a battery-/suspend-/reboot-aware indexing system that has path/extension
white/blacklists and prioritizes file monitored changes. This way, searching
can happen against an optimized text search DBMS much faster than waiting for
zillions of IOPS that are basically wasted by instead spending them ahead-of-
time in the background/idle indexing text files/metadata/structured data once
when it changed/s and already know exactly where all occurrences of
_kWhateverCondition_PP3V42_G3H_ or _\A[AB]{1,3}c+d\z_ live under _~ /Projects_
without reading any actual files.

~~~
svnpenn
Yeah and its also 10 times larger

[https://github.com/BurntSushi/ripgrep/issues/1481](https://github.com/BurntSushi/ripgrep/issues/1481)

~~~
reificator
If you go on a system with grep aliased and run your single grep command, are
you going to be able to tell which binary was larger?

If you look at the size of two disk images for different distros, and one has
grep while the other has ripgrep, are you going to be able to tell which is
which?

10x larger than grep is noise in 2020. Making that tradeoff in exchange for
significantly improved performance seems reasonable.

Not to mention a large part of that difference is likely due to grep relying
on libc, while ripgrep has to bundle its own runtime. And that's not even
bringing up memory safety.

I'll take ripgrep at 10x the size of grep any day.

------
twic
I often set the nullglob option in scripts, because it makes the handling of
globs which don't match anything a bit more predictable:

[http://bash.cumulonim.biz/NullGlob.html](http://bash.cumulonim.biz/NullGlob.html)

There's a note at the end about how with nullglob set, ls on a glob with no
matches does something surprising. This is a great illustration of how an
empty list and the absence of a list are different. Sadly it's rather hard to
make that distinction in shells!

I do wish that either shells had a more explicit syntax for globbing, or other
commands didn't use the same syntax for patterns. Then confusion like this
couldn't occur. An example of the former would be if you had to write:

    
    
      ls $(glob *.txt)
    

Here, the shell would not treat * specially, but rather you would have to
explicitly expand it. This would be a pain, but at least you wouldn't do it by
mistake!

~~~
johncs
I set failglob: `shopt -s failglob`. Makes the whole command fail if there's
no matches. That combined with `set -e` which aborts the script in the event
of any command failing makes me feel somewhat safe.

Indeed I add the following two lines to every bash script I write:

    
    
        set -exu
        shopt -s failglob

~~~
nothrabannosir
If you like set -e, I recommend looking at set -o pipefail.

------
nothrabannosir
Tangential: another safeguard you can adopt is avoiding "hard delete" commands
like rm and find -delete. Untrain yourself from these commands by never using
them. On Mac systems, the "trash" program (brew install trash) sends files to
your system trash. You can use `trash [file]` and `find .. -print0 | xargs -0
trash --`. rm is a dangerous command you should only very rarely be using.

I fish something out of the trash a few times a year and lemme tell ya; it's
worth the investment.

Another tip if you fancy debugging shells is using

    
    
      python -c "print(__import__('sys').argv[1:])" sample "arg here" * foo
    

this provides the same functionality as the c program in TFA, without needing
gcc.

~~~
icebraining
Trash is the poor man's backup system.

~~~
JulianWasTaken
You use trash _and_ backups.

Rich men can still save a few dollars for pocket change.

------
tzs
For a long time (probably since the first time I forgot to quote something and
got burned, so around 40 years), I've thought that there should be some
mechanism for the shell to pass in information about how each argument came
about.

For each argument, it would tell the program if it was supplied directly, or
came from wildcard expansion. For those from wildcard expansion, it would tell
the program what the wildcard was.

Most programs would not care, but some programs could use this to catch common
quoting errors.

~~~
jolmg
> For those from wildcard expansion, it would tell the program what the
> wildcard was.

Different shells have different globbing mechanisms. Why should all programs
tie themselves to the mechanisms of any one particular shell?

The simpler the calling mechanism for executables, the simpler it is to write
them in any existing or future language. This also gives more flexibility to
future shells.

UNIX is pretty much designed thinking of users as programmers. Making it easy
to write programs building on other programs is as important as being able to
call them. With that in mind, I don't think it's a good compromise to
complicate the writing of executables in order to protect users from their own
mistakes.

~~~
tzs
> Different shells have different globbing mechanisms. Why should all programs
> tie themselves to the mechanisms of any one particular shell?

I don't think my proposal would do that.

First, a clarification. When I said "For those from wildcard expansion, it
would tell the program what the wildcard was" I meant the shell tells the
program the full argument containing the wildcard, not just the wildcard part.
E.g., if the argument was a?c which expanded to abc, the shell would tell the
program it was a?c, not merely ?.

Let's say myprog takes one argument, which it expects to either be a file name
or a wildcard in some pattern language that is not necessarily the same
pattern language used by the shell.

Suppose myprog is invoked and it sees it has one argument, X. If the shell
tells it that X did not come from shell wildcard expansion, myprog can safely
use it.

If it does come from wildcard expansion and the source was Y, then there are a
few cases.

1\. Neither X nor Y contains any myprog wildcards. In this case, I'd have
myprog go ahead and use X.

2\. X does not contain any myprog wildcards, but Y does. Myprog can infer from
this that it and the shell probably have overlapping wildcard languages.
Report a "needs quote?" error.

3\. X contains a myprog wildcard, but Y does not. Probably myprog and the
shell use different wildcard languages. I'd guess its pretty unlikely that the
user expects that a filename will contain a myprog wildcard, so I'd report an
error in this case.

4\. Both X and Y contain myprog wildcards. Go ahead an accept X, applying
myprog wildcard expanstion to it. (Maybe first check that X and Y contain the
same myprog wildcards, in the same order).

I'd probably add support in myprog for some optional flags to change the
defaults in those cases so if you really want to do obscure things like have
file names that contain myprog wildcards and use shell wildcards to provide
those file names you can do it.

~~~
jolmg
Right now, programs receive a list of strings as their arguments. What would
be a concrete proposal for this X-Y mapping, taking into account that a single
Y results in multiple Xes?

The calls of executables is done via this system call:

int execve(const char * path, char * const argv[], char * const envp[]);

How would you modify that system call signature to be able to carry that
information? And what about how programs receive arguments?

int main(int argc, char * * argv)

How would you modify main()'s signature?

Take into account, the kernel has no notion that shells even exist. It has no
need to know about features of particular programs in the upper layers, but
now it's going to carry this information. All other programs, too. Right now,
they're typically not aware that there is such a thing in the world as a
shell, but now an integral part of what makes an executable an executable, its
arguments, is going to come attached to this data structure that represents
the use of a feature of some other program that has nothing to do with the
executable itself.

What is a wildcard/glob/pattern? It's just some weird idea a program not
different from any other program had. It's not particularly important. It's
nothing all other executables ever needed to know about before.

Sorry I'm ranting. What I'm trying to convey is that typically software comes
in layers, like an upside down pyramid, and the upper layers base themselves
on the lower layers. The upper layers depend on the foundation that is the
lower layer. This seems to go backwards, with the lower layer basing itself on
a particular tiny insignificant piece of the upper layer. To the lower layer,
that piece from the upper layer doesn't even need to exist. It can just
disappear. The lower layer can run just fine without it. The kernel doesn't
need the shell, and even shells don't need globbing. It's not a core feature
even if it's common.

I'm fine with breaking rules and making a step towards a mess when the benefit
is really worth it, but I'm not convinced this is worth it.

Listen, this article says `find -name * .jpg` is a common mistake (I put the
space because of HN formatting). Yet, I don't think I've ever done that, and I
don't believe I ever will. I trust the claim to an extent. When people are
learning a new language (tongue), like English or Spanish, they'll make all
sorts of silly grammatical mistakes, like saying "you was late" or similar.
I'm sure they're very common, but as they gain experience or are a native
speaker, they'll never commit those mistakes. Trust me that `find -name *
.jpg` looks really wrong. It jumps out, and just like you'd never say "you was
late", my fingers would never type that.

I wouldn't try to change English grammar so that "you was late" became
acceptable. For whoever is making those types of mistakes, learning is a
process, and that's fine.

~~~
tzs
> What would be a concrete proposal for this X-Y mapping, taking into account
> that a single Y results in multiple Xes?

Two arrays:

1\. An array of all the Ys.

2\. An array with one entry for each X. If X came from shell wildcard
expansion, this entry is the index into the first array of the Y whose
expansion resulted in X. If X did not come from wildcard expansion, this entry
is some magic value that cannot be mistaken for an index into the first array.

Pass these arrays in the environment. No need for any kernel or standard
library or language runtime modification to support it.

------
dehrmann
Shell (because this is technically a shell, not a find issue) is the worst
language that everyone should learn. It's a language you'll actually
encounter, and it's one that's hard to avoid (unlike PHP).

------
seiferteric
This was obvious to me, but one version of this that surprised me is when
using scp. If you glob a remote destination like "scp myserver:*.jpg ./" It
will probably work! But how? Because the remote path will likely not match any
local files and the path with the asterisk will be passed to scp and scp will
do the globbing on the remote side.

~~~
tyingq
I mostly use ssh and tar instead of scp, because I'm usually after more than
one file.

Like, _" ssh remote 'cd /whatever; tar -cf - someglobpattern' | tar -xvf"_

~~~
emmelaich
Tip: get into the habit of using && rather than ;

So...

> _ssh remote 'cd /whatever && tar -cf - someglobpattern' | tar -xvf_

~~~
gdavisson
Seconded. Here [https://apple.stackexchange.com/questions/378942/cant-
initia...](https://apple.stackexchange.com/questions/378942/cant-initialize-
osx-interrogation-folder) is an example of what can happen from not checking
for errors after a `cd` command. Summary: "sudo find ... -delete" ran in the
root directory rather than the intended location, and now the OS is gone
(probably along with lots more).

~~~
tyingq
Fair observation. I will change my ways :)

------
ulrikrasmussen
I believe that programming languages should never make the meaning of a
program depend on the context in which it is executed. So many obscure bugs
are directly caused by such behaviors. There should be exactly one possible
interpretation for a given statement, and if that cannot be executed, then the
program should abort. In this case, the glob should never have been passed on
to find. It should either have expanded to the empty array, or failed.

~~~
madsbuch
One could argue that it is merely a side effect that a shell constitutes a
programming language. And one could also note that find should employ the same
tradition as the shell (ie. Use __/ *.jpg to recourse into folders)

------
umanwizard
My instant reaction to the example was “that won’t work; you’re shell will say
something like ‘no matches’”.

Using an unescaped star in a find command _never_ works for me, which is a lot
better than it sometimes working and sometimes breaking!

Reading the article and the comments, it seems like bash doesn’t do this? I
suppose it’s one nice thing about oh-my-zsh, whose default confit I use almost
unchanged.

~~~
erikbye
It's a default in zsh, nevermind oh-my-zsh.

~~~
umanwizard
Thanks; I didn’t know whether it was or not while I was writing my comment,
and it was difficult to check on mobile, so I went with what I knew for sure.

Glad to know it’s a stock zsh default, too!

------
mehrdada
Straight from _The UNIX-HATERS Handbook_.
[https://web.mit.edu/~simsong/www/ugh.pdf](https://web.mit.edu/~simsong/www/ugh.pdf)

~~~
fctorial
A classic

------
thundergolfer
Putting ‘shellcheck’ in your CI pipeline is a must for me now, after one too
many mistakes.

I just finished cleaning away all existing ‘error’ and ‘warning’ level issues
in our codebase so that the ‘shellcheck’ CI step can be really strict on code
quality.

------
arcade79
Subject of the post is wrong. This is a common mistake between the user and
whichever shell the user is using, not the user and the command itself.

The find command works exactly as expected.

------
thunderbong
Phew! I'm glad I've been hitting the "Happy Case" scenario all these years!

Very useful article. And very informative.

Summary:

Instead of -

    
    
      find . -name *.jpg
    
    

Use quotes around pattern i.e.

    
    
      find . -name '*.jpg'
    
    

Edit: Oops, the double-quotes should have been single quotes! Thanks, @lucd.
Happy case, like I said!

~~~
lucd
Wildcards are still expanded inside double quotes.. Yiu have to use single
quotes.

~~~
solarexplorer
...or a backslash.

~~~
beamatronic
I use the backslash. I also specify -type f explicitly when I’m looking for
files.

find . -type f -name \\*.txt

Now the next article will talk about problems when there’s a space in the file
names and you just piped the output into xargs :)

------
mynegation
Common? Yes. Simple enough to stop doing this mistake after two times? Also
yes. One you internalize in which case shell is responsible for globbing and
in which case command itself, it is pretty clear cut.

------
vikinghckr
`find` has one of the worst user experiences out of UNIX tools. I prefer to
use `find . | grep foo` to find files.

------
StreamBright
Isn't this in the Unix hater manual? I never use -name without ''. I guess
this is just muscle memory from early on when I run into this issue that in
Unix *.py can mean very different things depending on where it gets resolved.

------
madsbuch
That was a lot of text to explain that one should be cautious of the wildcard
expansion some shells provide.

Thanks! I would have jumped right in!

------
joana035
The title seems a bit off since shell expansions and arguments has nothing to
do with the find command.

Both features are also often covered in entry level material for introduction
to shell.

~~~
shmageggy
Well it seems the root of the problem is

> * Most importantly, the 'find' command uses a different algorithm than shell
> globbing does when matching wildcard characters. More specifically, the find
> command will apply the search pattern against the base of the file name with
> all leading directories removed. This is contrasted from shell globbing
> which will expand the wildcard between each path component separately. When
> no path components are specified, the wildcard will match only files in the
> current directory.*

So there does seem to be a `find` specific issue here

~~~
Izkata
That's just ignorance about find. The globbing works fine, they're just not
doing the search they think they are - they seem to think "-name" acts like
"-path":

    
    
      $ ls Foobar/
      one  three  two
      $ find . -path '*bar/t*'
      ./Foobar/two
      ./Foobar/three

------
siddharthgoel88
It is just awesome that I stumbled upon this post. I remember previously I had
faced similar issue while running a command like

    
    
      find . -name *.gradle | blah blah 
    

Instead of finding the root cause, I by-passed it by

    
    
      find . | grep "\.gradle" | blah blah
    

It just feels great to now connect the dot and know the real reason for the
issue.

------
sys_64738
find . -name \\*.jpg

This is pretty elementary which any seasoned Linux person should know.

------
jancsika
> You can type: man glob

Translation: you cannot type "man" followed by an asterisk because that would
have required forethought in how one learns a programming language.

Argle: Hey Bargle, is that new bridge built to spec?

Bargle: It's like I always say, man: _good enough for shell script manual
operator discoverability_.

Argle: Yeah, you're always saying that...

------
rootusrootus
I almost appreciate the idea of writing a C program whose sole purpose is to
show you the arguments send to it. That's some serious overkill.

But I think echo *.py would not just be easier, but more effective at
demonstrating what your find command line will actually look like after shell
expansion.

~~~
mkl
That will be quite misleading when you have filenames with spaces and
arguments with quotes.

------
tzs
Another one I've seen a few times with find (although it is actually more an
xargs thing than a find thing), usually not with any bad consequences at
least, is something like this:

find . -type f | xargs grep foo

You expect to see all the "foo" lines from your files, each prefixed with the
file name and a colon. And that's what you get most of the time.

But sometimes you might get a foo line without the filename prefix.

Why? Because grep only adds the filename prefix when there is more than one
filename argument. There are two ways that might come about in the above
command.

The first is if the find only finds one file.

The second is if the find finds so many files that xargs has to invoke grep
more than once. It can happen that there is only one file left to do when it
gets to the final grep invocation.

Simple fix:

find . -type f | xargs grep foo /dev/null

~~~
Xophmeister
A “better” fix would be:

    
    
        find . -type f -exec grep -H foo {} +

~~~
dmurray
Yeah, find ¦ xargs is definitely an antipattern, but in practice I use it all
the time. Either because I forget the syntax for find -exec, or because I'm
feeling principled that find -exec breaks the Unix philosophy of doing one
thing well and being composable, or because my script started using ls and got
changed to use find.

~~~
cellularmitosis
Why is find | grep an anti-pattern? Is eschewing memorizing the flags of one
particular command in favor of using a pipeline which is much more broadly
applicable really an anti-pattern?

Heck, I’m at the point now where I pipe tar into gzip.

~~~
jrockway
I think there is a cottage industry around telling people that they're using
the interactive shell wrong. This all started with "useless use of cat", which
people still bitch about on Reddit and Twitter on a regular basis, and so
whenever someone finds something a little weird about UNIX, they are quick to
call a person asking a question about it dumb. I think it might be stockholm
syndrome, or a symptom of one's greatest achievement in life thusfar being
reading the man page for find. Or maybe they genuinely think they're helping.
I dunno.

Ultimately, it's a cascading failure of bad design. Good design is that find
and xargs each do one thing and do it well. Find can output files to anything!
Xargs can xargify input from anything! Bad design is that find uses \n as the
output record separator and that xargs uses \n as the input record separator,
but \n can appear in filenames! This design can never work and will always
lead to difficult-to-debug problems. So instead of fixing it, we blame the
user for not knowing "oh, well find has xargs built in. sort of. a lot of the
features are there. not all of them. but some. so never use find | args,
smile." or "well, we designed the unix shell to be easy to use... but there is
this corner case that we knew about and could have protected you from, but we
chose not to, so 1% of the time you'll rm -rf / with your xargs command,
UNLESS YOU REMEMBER THIS ONE WEIRD TRICK which is to use -0 to use an out-of-
band symbol to separate records which we could have just made happen by
default but chose not to, just to mess you up!"

I appreciate the efforts of people that are re-imagining the interactive
shell, like PowerShell. I am not very productive with PowerShell (to get a
listing of files in your directory, just type "Could-We-Make-It-Even-More-
Verbose -PerhapsInTheNextVersionWeWill!") but it's a good prototype of a good
shell. I have personally stepped on enough UNIX landmines to be generally OK
with the compromises, or more typically don't write shell scripts for anything
that will be run more than twice. It's bad though, and I don't think the users
are to blame.

~~~
thaumasiotes
> Bad design is that find uses \n as the output record separator and that
> xargs uses \n as the input record separator, but \n can appear in filenames!
> This design can never work and will always lead to difficult-to-debug
> problems. So instead of fixing it

Perhaps, but it also can't be avoided. Everything can appear in filenames. We
want filenames to be able to contain any character.

The most high-profile attempt to "fix" the "problem" you identify here is of
course the ASCII standard, which defines several separators (0x1C - 0x1F) just
for the purpose of delimiting fields with bytes that can't appear in data.
Except of course nobody cares -- the solution was stillborn -- because data
can contain any bytes that anyone wants it to.

> I am not very productive with PowerShell (to get a listing of files in your
> directory, just type "Could-We-Make-It-Even-More-Verbose
> -PerhapsInTheNextVersionWeWill!")

Well, you could do this by typing Get-ChildItem, but it would be both easier
and more standard to type one of "gci" (what Microsoft would like you to use),
"ls" (meant for those used to unix) or "dir" (for those used to dos).

~~~
unilynx
> Perhaps, but it also can't be avoided. Everything can appear in filenames.
> We want filenames to be able to contain any character.

Who is "we" ? I wouldn't mind some 'sane' limits, eg UTF8, no control
characters and no names starting with a dash.

Still hoping for the day that some distribution sets a mount option to enforce
sane filenames by default and starts weeding out the application bugs it'll
trigger..

[https://dwheeler.com/essays/fixing-unix-linux-
filenames.html](https://dwheeler.com/essays/fixing-unix-linux-filenames.html)

------
JosefAssad
Do people really use find like that to clean up source code?

    
    
      git clean -fxdn  # review what would be deleted, then
    
      git clean -fxd

~~~
Hamuko
I do for .pyc files.

    
    
      find . -name "*.pyc" -delete

~~~
JosefAssad
Is there a reason you prefer that rather than having something like

    
    
      *.py[cod]
    

in your .gitignore?

~~~
Hamuko
Yeah, the reason is that the Python interpreter doesn't give a shit about
.gitignore.

------
tigrezno
Apparently, the OP read the man page of " _glob_ " but couldn't spend a single
minute reading the man page of _FIND_.

    
    
      -name pattern
    
        ... Don't forget to enclose the pattern in quotes in order to protect it from expansion by the shell.
    

So, a lengthy article on an already documented feature of _find_.

------
tyingq
Globbing is also more complex than it seems on first blush.

Alternation is supported in bash. Stuff like _" echo ∗.{png,jp{e,}g}"_ (utf8
asterisk to get around HN, cut/paste won't work).

That bsd derived glob is useful for some sometimes useful tricks. Like in
Perl:

use File::Glob qw/bsd_glob/;

my @list = bsd_glob('This {list|stuff} is nested {{very,quite} deeply,deep}');

~~~
acqq
> "echo ∗.{png,jp{e,}g}" (utf8 asterisk to get around HN, cut/paste won't
> work)

This works:

    
    
        echo *.{png,jp{e,}g}
    

Note

    
    
        ∗ ⟵ U+2217   * ⟵ needed ASCII asterisk
    

Just put the code examples in the _separate lines, prefixed with spaces_.

------
alleycat5000
One of my favorite features of fish shell is the __wildcard expansion:

[https://fishshell.com/docs/current/tutorial.html#tut_wildcar...](https://fishshell.com/docs/current/tutorial.html#tut_wildcards)

It's rare I reach for find nowadays since switching.

------
7oi
Also, a good thing to remember is to mind the order of your options. I know
from experience that it matters a lot after thinking once: "I can just place
this `-delete` option wherever, right?" and using it as my first option.
Needless to say, I had a very bad time.

------
NotSammyHagar
It is unexpected to new users, principle of lead surprise should show it's not
a great idea. At the same time, globbing is a basic concept for beginning
shell users. I don't know how I learned about it, if someone told me or
something.

------
mangix
I wonder if this is also a problem with fish. The globing there is different.

~~~
faho
Fish won't pass along the unmatched glob, so in the given example you'd notice
that with

    
    
        find . -name *.py
    

it will error initially, because there is no "*.py" in the current directory.

Globbing is still a thing fish as the shell does, and you still need to
protect asterisks that need to reach commands, but you're more likely to
notice.

(for bash there is also the "failglob" option that I personally recommend)

Disclaimer: I am a fish developer.

------
fouc
I always write it like this:

    
    
      find . -name \*.jpg
    

escape the glob

------
dkarras
I also have the habit of always using -iname instead of -name to make case
insensitive searches.

~~~
manaskarekar
I used to do this until just replacing it with `fd`.

[https://github.com/sharkdp/fd](https://github.com/sharkdp/fd)

------
enriquto
Find is an ugly beast. I only use it to print all the files and then grep my
way on.

------
emmelaich
Quiz; in any directory, full or empty I can run this command

$ *

and get

*

What allows me to do this? (the $ is the prompt, not what I typed)

~~~
iudqnolq
You can't, at least on bash version 5.0.3(1)-release with the default config
Ubuntu packages it with. After a lag I get the error `$folder_name$: command
not found`

~~~
emmelaich
I promise you you can, with a previous particular incantation.

Answer to come.

PS. the response is not important.

~~~
iudqnolq
Oh, I thought you meant in an arbitrary directory. If the first file in sorted
order is executable and prints "*" to stdout you could get that.

~~~
emmelaich
I did mean an arbitrary directory.

Your answer almost works; but only if PATH includes the current directory
which is unusual.

It does hint at another _almost_ answer ...

    
    
       mkdir t
       cd t
       ln -s $(type -p ls)
       *

------
shmerl
TL;DR: globbing kicks in before other things unless you turn it off like with
single quotes:

[https://www.tldp.org/LDP/abs/html/globbingref.html](https://www.tldp.org/LDP/abs/html/globbingref.html)

Don't forget about globbing when making Bash scripts.

~~~
sengstrom
points for spelling globbing correctly :)

------
vmchale
I use fd-find and I don't really miss find.

------
monkeycantype
at my workplace I use git bash on windows, and because i'm always getting man:
command not found I flick to a browser and type man <whatever I was looking
for>

About once a year I forget what happened all the previous times I typed

    
    
       man find 
    

into google.

TLDR: looking for Dennis Ritchie, I found Chuck Tingle.

------
Lio

      find . -name *.jpg
    

TL;DR if you don’t wrap your wildcard expressions in quotes the shell will
expand them.

    
    
      find . -name ‘*.jpg’
    

so wrap them in single quotes so that they make their way to the find command
unexpanded.

------
jasonhansel
This is the _one_ thing I like about DOS/cmd.exe. In those shells, wildcard
expansion is done by applications instead of the shell itself, so there's no
need to resort to hacks like this.

~~~
mkl
That means the expansion is very limited and can be inconsistent. The bash
etc. way is much more powerful and convenient.

