Re: I go crazy with windows filenames with spaces!
by Corion (Patriarch) on Jan 19, 2010 at 14:47 UTC
|
Most likely this is because when you shell out to `cd`, you get whitespace at the end of your directory. If you run with warnings enabled, Perl will tell you when you try to open a file with a newline at the end of its name. But maybe you did want to use Cwd instead anyway? Or File::Find?
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: I go crazy with windows filenames with spaces!
by ikegami (Patriarch) on Jan 19, 2010 at 15:15 UTC
|
In both snippets, right before opendir, print $path. You'll notice they're different.
"c:/documents\ and\ settings/username/desktop/perf_analyzer"
is the same thing as
"c:/documents and settings/username/desktop/perf_analyzer"
Both of the above produce the string
c:/documents and settings/username/desktop/perf_analyzer
Expressions that produce the string
c:\documents and settings\username\desktop\perf_analyzer
would also be fine. Your bug is
$path=~s/\s{1}/\\ /g;
You are causing the string to become
c:/documents\ and\ settings/username/desktop/perf_analyzer
That's bad, because there's no directory c:\documents
Fixed code:
chomp( my $path = `cd` );
opendir MYDIR, $path
or die("Can't open dir $path: $!\n");
Even better:
opendir MYDIR, '.'
or die("Can't open current dir: $!\n");
| [reply] [d/l] [select] |
Re: I go crazy with windows filenames with spaces!
by Anonymous Monk on Jan 19, 2010 at 14:49 UTC
|
You're asking why the shell command CD outputs what it does? Crazy indeed :)
$ cd |od -tacx1
0000000 D : \ p o r t a b l e a p p s c
+r
D : \ p o r t a b l e a p p s \
+r
44 3a 5c 70 6f 72 74 61 62 6c 65 61 70 70 73 0d
0000020 nl
\n
0a
0000021
use Cwd;
use Cwd;
print cwd(),"\n";
| [reply] [d/l] [select] |
Re: I go crazy with windows filenames with spaces!
by ahmad (Hermit) on Jan 19, 2010 at 15:03 UTC
|
my $path = 'C:\Documents and Settings\Administrator\Desktop';
opendir(DIR,$path) or die $!;
while (my $File = readdir DIR) {
print "$File\n";
}
closedir(DIR);
As I remember older versions of windows only support 8 characters long file/folder name so you'll have to use 6 characters and add ~1 at the end of the file name.
I am not very sure I haven't used old windows OS from like 6 years now
| [reply] [d/l] |
|
If you are running on windows XP or higher you don't need to escape the blank space.
OS doesn't matter. opendir always takes a path for argument. Not a path that's been escaped into something else.
As I remember older versions of windows only support 8 characters long file/folder name so you'll have to use 6 characters and add ~1 at the end of the file name.
You're saying there exists a version of Windows that both supported long file names and didn't support long file names.
DOS was what didn't support long file names. DOS applications running on Windows had to use the short path names. Adding ~1 is not the correct way of getting the short file name. And finally, the problem at hand has nothing to do with long file names. Or file names at all, really.
| [reply] [d/l] |
|
Win32::GetShortPathName($fullpath);
| [reply] |
|
use Win32::API;
sub GetShortPathName
{
my $GetShortPathName = new Win32::API('kernel32', 'GetShortPathName
+A', 'PPN', 'N');
die "Can't import API GetShortPathNameA:\n$!" unless defined $GetSh
+ortPathName;
my $longpath = shift;
my $length = 1 + length $longpath;
my $shortpath = ' ' x ($length);
$length = $GetShortPathName->Call($longpath, $shortpath, $length);
return substr($shortpath, 0, $length);
}
| [reply] [d/l] [select] |
|
|
|
All right!
My first code works if I chop what I get from cd, so:
$path = `cd`;
chop $path;
opendir MYDIR, $path;
print "Path:\n$path\n";
while (
$file = readdir(MYDIR))
{
+
print "File: ", $file, "\n";
}
One can really go mad when dealing with filenames in Windows. Greetings Bill...
Thanks! | [reply] [d/l] |
|
None of the problems you experienced are in any way related to Windows. The program would behave identically on any other OS*.
{Bashing someone else for your own errors}--
The space you are getting is not a space at all. It's the linefeed at the end of the line cd outputted. chomp is a better way of removing it.
* — Actually, it'll work even less because `cd` won't work on other OSes. It only works on Windows because of a bug in the Windows part of Perl. If `cd` did work elsewhere, the rest of the program would behave identically.
| [reply] [d/l] [select] |
|
| [reply] |
|
|
|
|
|
Re: I go crazy with windows filenames with spaces!
by Marshall (Canon) on Jan 19, 2010 at 23:20 UTC
|
I don't understand what your second code is supposed to do.
The most portable way to get the "files" in a directory is to just open that directory and use grep{} to filter the names that you want. See below. Note that readdir does not give full paths, you have to prepend the directory to the $_ variable.
Use '/', forward slash instead of '\' for file names. Windows Perl will do the "right thing". There is no need for '\\' and "backslash" unless some pathname has to go to the Windows shell.
Updated: to show map{} function better.
#!/usr/bin/perl -w
use strict;
my $user = 'SOME_USER';
my $directory = "c:/documents and settings/$user/";
opendir (MYDIR, $directory) || die "unable to open $directory";
my @file_paths = map {"$directory/$_"}
grep{ -f "$directory/$_" } readdir MYDIR;
# The below means the same thing. But I think that the
# above grep/map filter combo is easier to understand.
#my @file_paths = map { -f "$directory/$_"
# ? "$directory/$_"
# : ()
# } readdir MYDIR;
#
# return"()" from a map{} to return "nothing"
# to get all the files (directories are files)....
# my @file_paths = map{ "$directory/$_"} readdir MYDIR;
foreach my $file (@file_paths)
{
print "$file\n";
}
| [reply] [d/l] |
|
| [reply] [d/l] |
|
I said that: Windows Perl will do the "right thing". That's a bit different than "Windows does the right thing". Perl has an amazing capacity to "un-screw" Windows quirks.
| [reply] |
|
|