Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

CPAN Module for mixing Unix/Windows path

by rovf (Priest)
on Jun 05, 2008 at 11:00 UTC ( [id://690394]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks!

I'm working at an application dealing with Windows and Unix in a pretty mixed up fashion, and so the usual problem with the pathes pops up. Internally, I use / as a separator whenever possible. For path strings I get from the "outside", I use File::Spec to be OS independent. I have also had a look at Path::Class on CPAN, but so far not needed it yet.

Occasionally, I need to compose a path consisting of several parts, where some parts are in Windows style and some in Unix style, and I need to produce from this a consistent path out of it. For example,

makepath('/home/foo/abc','bar\baz')
should yield '/home/foo/abc/bar/baz'.

Now of course this is easy to do: In this case, I just need to translate the backslashes into forward slashes; but I wonder whether someone knows already a CPAN module which has a collection of utilities similar to this one (this was only one example of what I need to do), so that I don't have to reinvent the wheel.

-- 
Ronald Fischer <ynnor@mm.st>

Replies are listed 'Best First'.
Re: CPAN Module for mixing Unix/Windows path
by lodin (Hermit) on Jun 05, 2008 at 11:57 UTC

    Path::Class, which you've already looked at, actually seems like a good one. It conveniently has the new_foreign and as_foreign methods. So you can do

    use Path::Class; my $path = dir($from_outside)->as_foreign('Unix');
    and $path will be Unix style. So if you normalize your paths, i.e. consistantly make your paths into the same type, when you first see them you don't have to worry about it later on. Everything will Just Work. If you know that a path from outside is of a non-native type you can use foreign_dir($type, $path) instead.

    Nowadays I pretty much only use Path::Class instead of File::Spec because path manipulation quickly gets dirty and Path::Class has handy methods, while retaining a good control of what's what regarding file system type and file/dir.

    lodin

      Though Path::Class seems to be really good (and maybe I should have used it in place of File::Spec from the beginning), I don't see how it can handle my case, as it seems to require the *caller* to already know which style the pathes are.

      For example, when running the following piece of code:

      use Path::Class; foreach $s ('x/y','x\y') { $dir=Path::Class:Dir->new($s)->as_foreign('Unix'); print "$dir\n"; }
      I would have wished that this would output
      x/y x/y
      no matter whether the application is running on Unix or on Windows. But on Unix (for example), I get
      x/y x\y
      I understand the behaviour of Path::Class: It is not designed to look into a path string and guess from there what OS type it is supposed to be - but this is the very thing I'm looking for.

      -- 
      Ronald Fischer <ynnor@mm.st>

        I don't quite understand the problem.

        From the OP: Internally, I use / as a separator whenever possible. For path strings I get from the "outside", I use File::Spec to be OS independent.

        Do any paths come from somewhere else, that you can't keep track of and normalize? My point is that Path::Class, just as File::Spec which it uses internally, expects Unix style paths when run on Unix, and Windows style paths when run on Windows, unless you tell it otherwise. So for new never-before-seen paths you do

        my $path = dir($from_outside)->as_foreign('Unix');
        and once they're internal, you just do
        my $path = foreign_dir('Unix', $internal);
        Is this unapplicable to your problem?

        lodin

        I understand the behaviour of Path::Class: It is not designed to look into a path string and guess from there what OS type it is supposed to be - but this is the very thing I'm looking for.
        I suspect this a difficult task, as '\' is a legal character in Unix filenames.
Re: CPAN Module for mixing Unix/Windows path
by ikegami (Patriarch) on Jun 05, 2008 at 11:15 UTC

    Your makepath sounds like File::Spec's catdir. catdirwill return a consistent result, but the opposite of the one you asked for.

    I suppose you could use filter the output of catdir as follows

    use File::Spec::Functions qw( catdir ); sub lean_forw { my $s = @_ ? $_[0] : $_; $s =~ tr!\\!/!; return $s; } lean_forw(catdir('/home/foo/abc', 'bar\baz'))
      Maybe I misread your 'consistent', but for me
      use File::Spec::Functions qw( catdir ); print catdir('/home/foo/abc', 'bar\baz');
      gives
      /home/foo/abc/bar\baz
      which is not what I would have expected (i.e. either all forward or all backward slashes). This is perl 5.8.8. on linux

        Your test is invalid. File::Spec will never produce 'bar\baz'* on your system. Reread the OP.

        Update: I thought it went without saying given the context, but:
        * — where '\' is a path separator.

Re: CPAN Module for mixing Unix/Windows path
by syphilis (Archbishop) on Jun 05, 2008 at 11:06 UTC
    In many instances (especially with perl), the forward slash works just fine as a path separator on Windows. Does that simplify things for you in any way ?

    Cheers,
    Rob

      In this case, no, because if I have "control" over the strings, I use a / anyway all the time. Here is an example where it is not sufficient:

      I have a directory path with / as separator, and I want to append to this directory a relative path of subdirs. This path I get from %ENV. The user is allowed to use either Windows or Unix style separators. If I want to form a consistent path (say: Unix style), then I need to translate the backslashes in the user-supplied path to forward slashes.

      This is only a simple example. Other examples are: Translating a Unix path to Windows (for usage in a generated BAT file) or vice versa (for usage in a generated piece of bash script).

      Let me emphasize that all these transformations are easy to do. I just thought that *if* someone has published a module with such features, it would not only be helpful, but would maybe also contain other useful stuff for mixed-OS environment development.

      -- 
      Ronald Fischer <ynnor@mm.st>


        If I want to form a consistent path (say: Unix style), then I need to translate the backslashes in the user-supplied path to forward slashes.


        (My original reply has already been downvoted ... which is not a good sign ... though that depends upon who downvoted it, and why.) On windows, I generally find that it doesn't matter whether the user supplies / or \ as the path separator. For example, this works fine for me on windows (where the /_32/pscrpt/inline folder exists):
        use strict; use warnings; use Cwd; my $path = '/_32/'; my $user_supplied = 'pscrpt\inline'; my $ok = chdir($path . $rel); print $ok, "\n", getcwd(), "\n"; __END__ prints: 1 C:/_32/pscrpt/inline
        In this case there's clearly no need for you to translate the backslashes to forward slashes. (I imagine that on Unix, however, things might be a little different :-)

        Other examples are: Translating a Unix path to Windows (for usage in a generated BAT file)


        Windows bat files will recognise the forward slash as a path separator ... at least that was the case for my test. (My test was to add "C:/b" to the path via a bat file, then check that an executable in C:/b ran, even though C:/b was not my cwd.)

        Cheers,
        Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://690394]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-04-24 01:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found