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

In order to compose an answer to Private Utilities i was am about to rewrite a Windows™ only script named ncopy to be platform compatible. With that script I can do stuff like
c:\> ncopy \foo\bar\*.txt \-1\0N.dat\-2\file.dat
which copies
foo\bar\baz.txt to \bar\baz\foo\file.dat
and
foo\bar\xxx.txt to \bar\xxx\foo\file.dat.

Now, how do I handle the "*.txt" cross platform? Under Linux'n'stuff I get a list of files, under Windows I get the string and must glob mysyelf. MacOs? Be? ...? What's common practice?

Update:
Thanks @ll, for the suggestions so far. I've ended up using Win32::Wildcard and this is the outcome.


holli, /regexed monk/

2005-12-01 Retitled by broquaint, as per Monastery guidelines
Original title: 'writing portable file processing scripts that use placeholders in filenames'

  • Comment on writing portable file processing scripts that use wildcards in filenames
  • Download Code

Replies are listed 'Best First'.
Re: writing portable file processing scripts that use wildcards in filenames
by DrHyde (Prior) on Dec 01, 2005 at 10:11 UTC
    On OS X and BeOS, and anything else with a proper shell, that will do the globbing for you so you don't have to. I'm not sure about Amiga and VMS.

    For Windows, you should probably use File::DosGlob (which is core) or Win32::Wildcard.

      AFAIK AmigaDE (or Anywhere, or whatever the hell it's called these days) has a bash-compatible shell (though I'm not sure there's a Perl interpreter for DE). On AmigaOS you'll have to do it yourself, same goes for AROS.
Re: writing portable file processing scripts that use wildcards in filenames
by rinceWind (Monsignor) on Dec 01, 2005 at 11:33 UTC

    You might want to look at my module File::Wildcard, which can use regexp captures to derive the new filename. If you want to give this a go, please give me feedback on usability, documentation, etc. and I'm willing to help if you get stuck.

    --

    Oh Lord, won’t you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, won’t you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

Re: writing portable file processing scripts that use wildcards in filenames
by Perl Mouse (Chaplain) on Dec 01, 2005 at 10:27 UTC
    If you want to do glob processing yourself, you must make sure you get the unexpanded string. But that's something you have to handle in the shell - when it gets to your program it's too late.

    It's comparable with doing:

    mysub ("foo$BAR");
    in Perl. If you want mysub to deal with the interpolation, you shouldn't change mysub to prevent Perl doing the interpolation. Instead, you change the quotes, or escape the special symbols.

    It's the same with a Unix shell. If you want your program to do the globbing, prevent the shell from expanding the *. Use quotes, or a backslash.

    Perl --((8:>*
Re: writing portable file processing scripts that use wildcards in filenames
by tbone1 (Monsignor) on Dec 01, 2005 at 12:58 UTC
    I don't know that I'd worry about MacOS. It is old; it hasn't shipped as the primary OS since 2001. All the major apps have been converted/updated to OS X, which is a Unix under the hood. As a former longtime MacOS user, I have completely abandoned it. In fact, I can't remember the last time I've used it, even in the "Classic" emulation mode under OS X. Certainly not since 2002.

    Now, while this might be against the philosophy of open source/Perl/CPAN/etc, you might want to ask yourself if it's worth the time and effort.

    --
    tbone1, YAPS (Yet Another Perl Schlub)
    And remember, if he succeeds, so what.
    - Chick McGee

Re: writing portable file processing scripts that use wildcards in filenames
by halley (Prior) on Dec 01, 2005 at 15:52 UTC
    There's no harm in calling glob() on a filename with no wildcards. Just glob all but the last argument. You can use splice() to replace each element with its own globbed list, or you can map the sucker.

    As an aside, I think that weird path syntax is pretty bad. What do you do with paths that start with dashes?

    --
    [ e d @ h a l l e y . c c ]

      There's no harm in calling glob() on a filename with no wildcards.
      Indeed, there isn't.
      Just glob all but the last argument.
      No, that would be wrong. Just because globbing on a filename without wildcars is ok doesn't mean that the result of a glob gives you a fixed point.

      Suppose for instance you have a utility that removes those files that are given as argument (like rm does). Let's call it remove. But, unlike rm, it globs its arguments - even when working in an environment that globs. Suppose you have a directory that contains the following files:

      thesis_worked_on_for_the_past_four_years naked_perl_chicks.tar.gz parrot_1.0.0.tar.gz [a-z]*
      And you want to remove that pesky file named [a-z]*. You call your program like this:
      remove *a-z*
      If you had called rm, the first three files would still be there, with the pesky file removed. However, remove, globbing its arguments, will remove the first three files, leaving the pesky file where it is.
      Perl --((8:>*
        But that's not the syntax of the command the original poster was recalling. rm would glob ALL arguments. cp would glob all but the last argument, since the last argument is defined as the destination.

        Perl's glob() expands bracket classes in some versions, usually in the same environments where the shells do too. If you don't want the shell to expand bracket classes, you escape them at the shell level: rm '[a-b]foo', or rm \[a-b\]foo. If you have to pass a bracket class to a program which globs for you, even after the shell would normally escape it, you may need to escape it twice. If this is a really common concern, then the "portable" way would be more elaborate. But then again, command line arguments are never going to be 100% "portable."

        If your filesystem has allowed a ? or * in your filename, you'll need to use some more serious tools, because that's generally a filesystem bug.

        --
        [ e d @ h a l l e y . c c ]