Re: Platform independant directory separator
by rinceWind (Monsignor) on Mar 01, 2004 at 14:08 UTC
|
I want to get the current OS directory separator into a var so that I can use it in string substitution.
On some platforms, there is not a single separator. VMS for example has the syntax
DEVICE:[DIR.PATH]FILENAME.EXT;VER
Although '.' is the separator between components of the path, the whole directory is encased in brackets.
I advise going with what others suggest, with File::Spec and File::Spec::Functions. Note that the functions splitpath and splitdir do what you are looking for, returning a list of path elements (list context). You can work on the list of strings and join them back together again with catpath or catdir.
Note that all O/S that run Perl support POSIX filenames, which means that you can use forward slash as a directory separator. This is how the standard module installs work, supplying filespecs such as t/mytest.t and -Iblib/lib.
Also note that usually you cannot mix native and POSIX directory separators (Windows lets you get away with it sometimes). So to write portable code that works with native filespecs, I recommend sticking to File::Spec.
See also the slides for a talk I gave recently on portability.
-- I'm Not Just Another Perl Hacker
| [reply] [d/l] |
Re: Platform independant directory separator
by Roger (Parson) on Mar 01, 2004 at 12:36 UTC
|
Use the canonpath function in the File::Spec::Functions module. It's part of the Perl's core distribution.
use File::Spec::Functions qw/ canonpath /;
# it's a good idea to use relative path for portability
my $platform_independent_path =
canonpath "../data/somepath/somedata.txt";
my $directory_separator =
canonpath "/";
| [reply] [d/l] |
|
|
my $platform_independent_path =
canonpath "../data/somepath/somedata.txt";
my $directory_separator =
canonpath "/";
Erm. No.
All canonpath does is clear up a directory in to a canonical for for a specific platform - it's not platform independent in any way.
For example running your code on a Mac OS 9 box would set $directory_separator to "/" when it would more accurately be ":".
As rinceWind points out the idea of a single separator isn't valid on some platforms in any case.
| [reply] [d/l] [select] |
Re: Platform independant directory separator
by tinita (Parson) on Mar 01, 2004 at 12:28 UTC
|
uhm, you could use File::Spec::catfile, like
my $sep = File::Spec->catfile('', '');
i actually wonder why File::Spec doesn't provide a
variable for this...
Update: ok, after reading rinceWind's answer I can see why. | [reply] [d/l] |
Re: Platform independant directory separator
by Hena (Friar) on Mar 01, 2004 at 12:29 UTC
|
Try module File::Spec (perldoc File::Spec). It provides a set of functions to handle paths. | [reply] |
Re: Platform independant directory separator
by Grygonos (Chaplain) on Mar 01, 2004 at 12:27 UTC
|
$^O tells you what OS is running. You can use / or \\ accordingly then. In most cases, the / version works for both OS's. However in certain modules like Win32::OLE the Windows style \\ must be used. Checking $^O is always safe though.
| [reply] [d/l] [select] |
|
|
> You can use / or \\ accordingly then.
but there are more than two operating systems...
| [reply] |
|
|
Yes, but this will work for 99% of most applications. Treating Unix/Linux/MacOS as "not Windows" covers nearly everything for x86, IA64, IA32e, and Mac PPC hardware -- maybe more. It's one thing to say "platform independance" but it usually means "Windows and some UNIX-like systems and maybe Netware and OS/2". Depends on what you want to run on.
| [reply] |
|
|
Re: Platform independant directory separator
by Crian (Curate) on Mar 01, 2004 at 12:33 UTC
|
I searched for a special perl var for your purpose without success.
Perhaps the following fact will help you(?):
You can use slash (in the most cases) as directory seperator under Windows systems too.
But beside Unix/Linux and Windows I don't know what seperators are in use and if slash could be also used. | [reply] |
|
|
What you actually mean is that the file system operations that Perl give you have had an inline tr!/!\\! added during the port to windows so that scripts written for UNIX will run OK. External commands only respect the backslash.
| [reply] [d/l] |
Re: Platform independant directory separator
by QwertyD (Pilgrim) on Mar 02, 2004 at 01:10 UTC
|
While the suggestions of File::Spec are spot on, the module is not without its problems. Its functionality is fine. Its interface, on the other hand, (which somehow tries to be OO but isn't really) gives me a headache whenever I try to figure out how to use it.
I reccomend Path::Class. It provides a much nicer object oriented interface that wraps the File::Spec functions underneath. It makes infinitely more sense, and is much more readable.
Once it's Turing complete, everything else is just syntactic sugar.
| [reply] |
Re: Platform independant directory separator
by coreolyn (Parson) on Mar 01, 2004 at 16:00 UTC
|
This is going to be a lot more answer than you are looking for but as you are in a cross-platform situation I thought I'd share what I have found to be a very re-usable format. I'm in a situation where CPAN is difficult to utilize effectively in our organization, so I created a module I called OSify.pm. In it I created common OS commands OSrecursive copy, OSmkdir, etc and centralized their logic, It has made it so I can code for DOS, linux, and Solaris with the same commands easily, and can be quickly extended to other OS's as required. The following is just the OSPath() that takes care of the delimiter issue, but using the general approach it's easy to adapt to any given command.
sub OSpath {
$_ = $_[0];
debug( "Recieved path as\n $_\n", 0 );
if ( $^O =~ /mswin/i ) {
# Everywhere you find a forward back slash replace it with
# two backslashes
if ( /(\/|\\\w)/ ) {
s/(\/|\\)/\\\\/g;
}
# Incase we've created four backslashes in a row
# reduceit back to one
if ( /(\\)(\\)(\\)(\\)/ ) {
s/\\\\\\\\/\\\\/g;
}
# Have to make sure there is only 1 slash after a drive letter
if ( /(\:\\\\).*/ ) {
s/$1/\:\\/;
}
} elsif ( $^O =~ /solaris/i ) {
s/\\/\//g;
if ( $_ =~ /.*\/(.*\s.*)\/.*/ ) {
my $spacedDir = $1;
unless ( $spacedDir =~ /"/ ) {
$_ =~ s/$1/"$spacedDir"/g;
}
}
} else {
print "Platform $^O is not currently supported\n";
}
debug( "Returning path as\n $_\n", 0 );
return $_;
}
| [reply] [d/l] |
|
|
| [reply] |
|
|
OSmkdir
OSpath
OSrmdir
OSworkdir (Make a temp directory in $TEMP with unique name)
OSlogger
searchReplaceCopyFile
printEnvVars
debug
getFileExt
getEnvVars
OScopy
OSdelete
singleDosDelim
file2Array
arrayRelevant
getShortPath
shortDirName (Dos 8 letter dirname)
OSrecursiveCopy
OSmkWritable
| [reply] [d/l] |
Re: Platform independant directory separator
by alg (Initiate) on Apr 19, 2023 at 02:08 UTC
|
Before File::Spec, this is what I used. It still works today and it worked on very old perls on every Unix-like and Windows platforms that I've ever encountered.
Basically, the idea is to ask perl what it uses as directory separator char.
Sample use ($dirSep gets either back or forward slash character):
$dirSep = ( $ENV{"PATH"} =~ m/;[a-z]:\\/i ) ? '\\' : '/' ;
print $dirSep;
| [reply] [d/l] |
|
|
| [reply] |