[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: find improvement wish

From: Chun Yip Wong
Subject: Re: find improvement wish
Date: Mon, 8 Feb 2021 12:17:04 +0800

Thanks for detailed explanation,

在 2021年2月8日 週一 11:47,Bob Proulx <bob@proulx.com> 寫道:

> Chun Yip Wong wrote:
> > I prefer using find with script in this way: find $dir $pattern.where
> > pattern=" -name *.sh ! -name *.txt ... etc."
> There is a problem with insufficiently quoted shell file glob meta
> characters in that pattern.  That's a problem unrelated to find.
> > The built findutils version is 4.7. it fails to work with such message
> >
> > find: paths must precede expression: 'test.sh'
> > find: possible unquoted pattern after predicate '-name'
> And there is a warning about "possible unquoted pattern" but since we
> can see the pattern we know that yes the pattern is not quoted and
> that is an error of the command line.
> > I know when there are multiple files, such as  a.txt b.txt c.txt, find .
> > -name *.txt will cause such messages and solve with quoted the '*.txt'
> > It is more convenient to define a pattern and no need to quote all
> > extensions one by one, line by line using scripts.
> The "*" file glob character is a shell meta-character.  The shell
> being your command line shell.  One of bash, ksh, zsh, or possibly
> even tcsh, csh, or possibly another.  The shell is not find.  The
> shell reads the command and expands shell file glob patterns like
> "*.txt" into files that match.  After the shell has expanded these
> characters then the resulting multiple arguments are passed to the
> command.  In this case the command find.
> In order to observe this expansion the "echo" command is most easily
> used.  If one uses echo they can see how the patterns are expanded.
> Or if there is no match then how it is not expanded.  It is a data
> dependent expansion based upon whether any files exist that match the
> pattern or not.  Which is why any characters that happen to be shell
> metacharacters must be quoted to prevent this expansion.  For use in
> the fine -name option it is not desired to have them expanded and
> therefore this must be prevented.
>     $ touch a.txt b.txt c.txt
>     $ pattern=" -name *.sh ! -name *.txt"
>     $ echo find $dir $pattern
>     find -name *.sh ! -name a.txt b.txt c.txt
> And here we see that -name *.txt is expanded to be -name a.txt b.txt
> c.txt when -name uses exactly one argument.  The "-name a.txt" is read
> and then b.txt and c.txt is extra and not part of -name.
> The expansion of the shell is useful for other commands that are not
> find to use.  For example they are useful with ls.
>     $ echo ls -log *.txt
>     ls -log a.txt b.txt c.txt
>     $ ls -log *.txt
>     -rw-rw-r-- 1 0 Feb  7 20:36 a.txt
>     -rw-rw-r-- 1 0 Feb  7 20:36 b.txt
>     -rw-rw-r-- 1 0 Feb  7 20:36 c.txt
> That is useful for ls and other commands but it is not useful for find
> and therefore those file glob characters, and other shell meta
> characters, must be quoted to prevent this expension.
> > I prefer using find with script in this way: find $dir $pattern.where
> > pattern=" -name *.sh ! -name *.txt ... etc."
> Quote the arguments.  Since this is in a double quoted string then it
> is convenient to use single quotes in the string.
>     pattern=" -name '*.sh' ! -name '*.txt' ... etc."
> And then the result will be this.  First a reminder of the problem
> case.
>     $ pattern=" -name *.sh ! -name *.txt"; echo find $dir $pattern
>     find -name *.sh ! -name a.txt b.txt c.txt
> And then we fix it by adding quotes.
>     $ pattern=" -name '*.sh' ! -name '*.txt'"; echo find $dir $pattern
>     find -name '*.sh' ! -name '*.txt'
> As some background information the "*" is called a file glob character
> and the expansion is called globbing (see "man glob") because the "*"
> matches a "glob" of file name characters.  A glob being a bunch of
> characters.  It's a very casual word idiom for a bunch of characters.
> This dates back to the earliest implementation of Unix.
> Bob

reply via email to

[Prev in Thread] Current Thread [Next in Thread]