http://www.perlmonks.org?node_id=725406

puterboy has asked for the wisdom of the Perl Monks concerning the following question:

I have 2 files: "/abc/Two Words" and "/abc/OneWord"

In perl, the following globs works: < "abc/Two Words" >
< 'abc/Two Words' >
< abc/OneWord >

but the following globs don't:
< 'abc/OneWord' >
< 'abc/OneWord' >
< abc/Two Words >

However in bash, all of the above work except for:
abc/Two Words (where quotes left off)

So, I guess I don't understand why in Perl the quoting affects files with spaces differently from files without. While in bash, the workings of glob seem consistent.

Am I missing something or doing something wrong here?

Replies are listed 'Best First'.
Re: Unexplained glob behavior vs. Bash shell
by moritz (Cardinal) on Nov 23, 2008 at 10:18 UTC
    One way to get a more consistent glob behaviour is to use File::Glob::bsd_glob (File::Glob is a core module since Perl 5.6). If I remember correctly you don't need to escape whitespaces with that one, and all quotes are taken literally.
Re: Unexplained glob behavior vs. Bash shell
by ikegami (Patriarch) on Nov 23, 2008 at 16:16 UTC

    These work as expected:

    $ perl -le'print for < abc/OneWord >' abc/OneWord $ perl -le'print for < abc/Two Words >' abc/Two Words $ perl -le'print for < abc/Two\\ Words >' abc/Two Words $ perl -MFile::Glob=bsd_glob -le'print for bsd_glob("abc/Two Words")' abc/Two Words

    Remember, space is a pattern separator unless you use bsd_glob from File::Glob. You need to precede it with a backslash for it to be interpreted literally.

    I can't account for the different in

    $ perl -le'print for < '\''abc/OneWord'\'' >' 'abc/OneWord' $ perl -le'print for < '\''abc/Two Words'\'' >' abc/Two Words

    You can get consistent behaviour by using bsd_glob or by treating ' as a meta character.

    $ perl -MFile::Glob=bsd_glob -le'print for bsd_glob("'\''abc/OneWord'\ +''")' 'abc/OneWord' $ perl -MFile::Glob=bsd_glob -le'print for bsd_glob("'\''abc/Two Words +'\''")' 'abc/Two Words'
    $ echo '< \\'\''abc/OneWord\\'\'' >' && > perl -le'print for < \\'\''abc/OneWord\\'\'' >' < \\'abc/OneWord\\' > 'abc/OneWord' $ echo '< \\'\''abc/Two\\ Words\\'\'' >' && > perl -le'print for < \\'\''abc/Two\\ Words\\'\'' >' < \\'abc/Two\\ Words\\' > 'abc/Two Words'

    So:

    • Escape spaces or use bsd_glob unless you want them treated as a pattern separator.
    • Escape quotes or use bsd_glob.

    I consider glob (aka < GLOBEXPR >) to be buggy and obsoleted by bsd_glob.

Re: Unexplained glob behavior vs. Bash shell
by genehack (Beadle) on Nov 23, 2008 at 14:15 UTC

    You say "works" and "don't work", but you don't say what you're trying to do. Are you trying to match one filename? both?

    Also note that glob()'s actions are modeled on csh, not bash, so that comparison may be leading you astray.