[LA.pm] perl/file path on mac x

Benjamin J. Tilly ben_tilly at operamail.com
Tue Feb 21 08:05:34 PST 2006


"David Heayn" <david at cloudgraphics.com> wrote:
> I am having a miserable time trying to figure out how perl sometimes
> can and can't read a string with a non-POSIX (?) compliant file path.
> 
> I'm trying to develop a cross-platform script for animators who
> needed to know not only how many frames had been rendered to a
> directory, but also quickly calculate estimated finish time, average
> frame render... blah blah blah.
> 
> The trouble arises when a mac user (maybe others) tries to point the
> script to watch "current directory" which lives in:
> 
> /users/bob/files and stuff/current render
> 
> 
> Now, it's very easy to:
> 
> % cd ../dir 2
> because mac's terminal program escapes the blank if the end user
> drags and drops the file into the cli,
> % cd /xzy/dir\ 2

Since I don't have a mac, it would help me a lot if you showed the actual debugging statements.

> If I have a perl script going and it asks for input
> % perl watcher.pl
> % Which directory to watch?
> I can then drag a directory right into the terminal, *have it
> escaped* automatically via mac x... but it "gets lost" within perl. I
> debugged it. I saw the escaped dir path, but perl failed every time
> it tried to switch directories. Somehow it seems to "unescape" in
> memory before it gets to it's final destination, or become useless
> when perl tries to chdir()

With the actual debugging statements I could figure this out.  Without, I can't.

> Now, I'm also working on something similar with regards to moving
> paths based on user input. Because I don't know how to correctly pass
> a file path correctly I did this hack for a HTML based gallery
> fixer-script. Hardcode a path in the script...
> 
> #!/bin/usr/perl -w
> use strict;
> my $w = "360"; # width of the PDF
> my $h = "465"; # height of the PDF
> my $bor = "1"; # border of the PDF
> my $path1 =
> "/Users/dave/Documents/T.L/Publish-\>Web/web-content/PDF/1/index.html";
> my $path2 = "/Users/dave/Documents/T.L/
> Publish-\>Web/web-content/PDF/2/index.html";

Note that the > character is in the path.  That can need escaping/unescaping depending on what is going on.

> print "*****  PDF -> WEB cleanup program\n";
> print "A - $path1\n";
> print "B - $path2\n";
> print "Index.html to modify?";
> my $choice = <STDIN>;
> my $fileLoc;
> if ($choice eq "A") {$fileLoc = $bus;}
> if ($choice eq "B") {$fileLoc = $mar;}

Umm...$choice will NEVER be "A" or "B".  It might be "A\n" or "B\n".  Could that be your problem right there?

I would strongly suggest changing that switch statement to look like this:

  if    ($choice eq "A\n") {$fileLoc = $bus;}
  elsif ($choice eq "B\n") {$fileLoc = $mar;}
  else {die "Unexpected choice '$choice'"}

to catch that kind of thinko.

> ###########
> #open(READFILE,
> "/Users/dave/Documents/T.L./Publish-\>Web/web-content/PDF/1/index.html")
> or die "Can't open file!!! \n";
> open(READFILE, "$fileLoc") or die "Can't open file!!! \n";

Try 3-argument open instead.

  open(READFILE, "<", $fileLoc) or die "Can't read '$fileLoc': $!";

Right now if $fileLoc had anything in it, I wouldn't be confident that > wouldn't be be interpreted as a shell character.  Of course $fileLoc is empty at the moment, which is a bigger problem.  But that aside, 3 argument open is generally safer, see http://www.perlmonks.org/?node_id=131085 for details.  (Note, chip is Chip Salzenburg, who definitely knows his way around Perl.)

Also note that I'm adding the filename to the die message.  That is a very helpful habit, because often variables don't have what we expect.  (It would have probably saved you this time!)  It is also a recommend from perlstyle.

> my $firstRead = <READFILE>;
> close(READFILE);
> 
> ##################################
> 
> No warnings.

I'm slightly surprised by that.  I'd expect an uninitialized value warning.

> Printing to screen works.
> Take input and branching works.

In your presented code it shouldn't work.  Are you SURE that it is working?  (Often when you stare at code and can't find the problem, the problem is an assumption that you haven't verified.  Hence the old saying, "Don't make an ASS of U and ME.")

> But, using the already hardcoded path does not (if it's in a
> variable). I get a failure.
> The paths were copied from the command line, "apple escaped" then
> inserted into my script, and they do exist on the hard drive, I
> checked them. I do have a directory named "Publish->Web", but, again,
> it is escaped... and therefore the problem is something else.
> 
> In the above script, there is a commented out line,
> #open(READFILE)...   which works but I want a way to pass a file path
> via variables to open(). I also have to destroy my choice A or B
> code, and manually edit the script before it runs. :(

OK, if that works then Perl ignores a > in the middle of your filename.  Good to know, but it still is a bad idea to rely on features that are likely to make even experienced Perl maintainers wonder.  (I'd prefer to be called "experienced".  It sounds soooo much nicer than "old". :-)

> My first guess is I have to do some escaping. But as I said before,
> they are escaped when viewed in the debugger. Any insights would be
> wonderful.

Hopefully I got the problem for you.

Cheers,
Ben


More information about the Losangeles-pm mailing list