[Top][All Lists]

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

Re: docs incorrectly mention pattern matching works like pathname expans

From: Stormy
Subject: Re: docs incorrectly mention pattern matching works like pathname expansion
Date: Fri, 16 Mar 2018 10:04:07 +0000 (UTC)

Robert, all,you are such friendly crowd.... maybe one day I'll write you about 
my car problems :) :) just kidding...
bash-only... :)
Thanks for the confirmation regarding the need to write code. and also about 
'cd' 'ls', yeah, it's what I sort of mean, bash does when passing args to them, 
but there is no other way to 'access' this type of parsing..

What you describe about splitting is what I ended up doing in my function, 
splitting on the "/", however, both paths need to be normalized fully before 
anything will work, like '/data//dir1' is same as '/data/dir1', so that is 
another effort/function (to normalize), again, cannot 'cd'/pwd to the location, 
b/c it may not exist.
also I'm completely unaware of the "-" in local, it gave me:
./fnmatch.sh: line 3: local: `-': not a valid identifier

took it out, and script seems to work, with the exception of the 
normalization.. anyways, I'm good, I'll get out of your way for now...
Thanks for the help, next time I can't figure out the most trivial bash issue, 
no more reading the FAQ, just straight to this email list :) :) :)
accept that as a compliment :)

PS: I was kidding of course - and u knew it.. so.. go with your instincts :)


    On Friday, March 16, 2018, 11:43:38 AM GMT+2, Robert Elz <address@hidden> 
     Date:        Thu, 15 Mar 2018 22:52:24 +0000 (UTC)
    From:        Stormy <address@hidden>
    Message-ID:  <address@hidden>

  |  but there is no way to make it do pathname matching internally. (cd, ls, 
will surely do it,

No, they surely don't - the pathname expansion that you seem to see in them is
done in the shell before they run.  "find" (and a few other commands) does 
matching, but there are only a few like that.

What might make things clearer is that in the normal case (I think bash has 
mechanisms that extend this) pathname matching is just pattern matching
applied to each component of the path name, one at a time.

That is, when pathname expansion is done (and it is attempted on every
unquoted argument to every command, unless turned off by "set -f") it works
by separating the word into components at the /s and then doing matching
using the list of patterns created by this, starting at the first, matching 
against the current directory (or the root directory if the path started with 
'/') matching the patten from next component against the file names in
that directory - then as it proceeds along the path name components, it
looks in every directory already found by earlier matching.

Whether the actual implementation works exactly like that or not does
not matter - there are some optimisations that can be used to speed
things up, but conceptually that is what happens.

The pattern matching that happens is identical here as it is in case
statements - the '/' does not match as it is not there in the patterns that
are used in the pathname match - the slashed were used to separate the
word into the list of component patterns, and removed (and because no
directory entry can contain a '/' character, so inventing some method to
allow it would be pointless).

Other matching, such as in case statements, simply uses the pattern
word as the pattern, regardless of what characters (including / are in it)
and matches it against some other string, which also might have / chars
in it.  The matching is identical, here / is just the same as any other
ordinary character - it is only special in path names.

You're right that if you want to test to see if a string will match another
string, as if one is a pathname pattern, and the other is a potential
file name, then you have to write code to do that (it is not something that
most people ever need to do...)

But something based upon


    set -f
    set -- $PATTERN

    for A in $PATHNAME
        [ $# -eq 0 ] && return 1

        case "$A" in
        $1)    ;;
        *)    return 1;;
    [ $# -eq 0 ]

is a few less than 40 lines, and should be approximately what is wanted
(note this has not been tested much - it is just intended as a hint)
Also note that since this uses "local" and particularly "local -" it is not
even slightly portable (though more than one shell can run it.)

usage is:

    fnmatch pattern potential-pathname

where you will usually need to quote the pattern arg (at least) to
prevent pathname expansion from altering it.

The result is its exit status. (so it can be used like

    if fnmatch ...


reply via email to

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