in reply to quoting/escaping file names

The shell's most likely your problem here, not Perl. Perl won't look at the contents of $filename if you interpolate it into a string, but the resulting string will be seen by a shell which will happily interpret $var if you're not careful.

The following works for me:

#!/usr/bin/perl use strict; use warnings; my $filename = q{$vaa it's not.txt}; $file =~ s/\$/\\\$/; my $exec = `touch "$filename"`;

The double quotes (in the `` string) are passed to the shell there, and ensure that the spaces in $filename won't be an issue. The regular expression adds a backslash in front of the dollar sign; this keeps it from being interpreted by the shell. Finally, the single quote in the filename is not considered special by either Perl or the shell.

Replies are listed 'Best First'.
Re^2: quoting/escaping file names
by Anonymous Monk on Sep 08, 2014 at 21:35 UTC

    It sounds like "$vaa it's not.txt" was only one example of a problematic filename, and so I gotta say I don't think your solution is general enough.

    Instead, I can only recommend to avoid the shell entirely (and only using the shell when you really know you really want its features - it really is another layer between Perl and the program you want to call, and you have to know how to use the shell, which isn't a given). This is possible via system (if you read its and the exec docs entirely because the invocation is a little tricky; and the output can be captured by something like Capture::Tiny), IPC::System::Simple, IPC::Run3, and a few others.

Re^2: quoting/escaping file names
by famatte (Novice) on Sep 09, 2014 at 01:06 UTC
    Hello
    Here's a pratical example
    while(<>) { my $filename = q{$_}; $filename =~ s/\$/\\\$/; my $exec = `md5sum "$filename"`; print $exec ."\n"; }

    My input
    /mnt1/$Recycle.Bin/S-1-5-21-3093161954-3233498542-1968413288-3198/$I7Q +M78L.pdf<br> /mnt1/$Recycle.Bin/S-1-5-21-3093161954-3233498542-1968413288-3198/$ID8 +4PBU.pdf<br> /mnt1/$Recycle.Bin/S-1-5-21-3093161954-3233498542-1968413288-3198/$IDL +L4FU.JPG<br> /mnt1/$Recycle.Bin/S-1-5-21-3093161954-3233498542-1968413288-3198/$IE2 +ZPET.xls<br> /mnt1/$Recycle.Bin/S-1-5-21-3093161954-3233498542-1968413288-3198/$IF7 +3ZR5.jpg<br>

     find /mnt1/\$Recycle.Bin/ -type f | hash.pl The result ..
    md5sum: $_: No such file or directory <br> md5sum: $_: No such file or directory <br> md5sum: $_: No such file or directory <br> md5sum: $_: No such file or directory <br>

    But As I said before. file names could have spaces and quotes..

    ps: I know there's a DIGEST::MD5. Its only an example

      Try removing this line:

      my $filename = q{$_};

      q// (or q{} etc.) is just the single-quote operator; I used that instead of the more customary single quotes to avoid having to escape the single quote in the string itself (which I felt would only serve to complicate the issue).

      See Quote and Quote like Operators and Quote Like Operators in perlop. Since this IS a single-quote, BTW, q{$_} (which is exactly the same as '$_') does not interpolate $_ into the string, and you end up passing a literal $_ to md5sum. And of course, it's unlikely that a file with that name exists.

      Long story short, just remove that line, it was just there to provide an example filename to work with.

      Why did you type  my $filename = q{$_}; what do you think that does?