in reply to quoting/escaping file names

I'm not exactly sure where your problem lies. Can you show us a short example program that demonstrate the problem you encounter, and also where you encounter it?

Maybe the part where you tried the substitutions and how they failed, and/or what you expected to happen?

Replies are listed 'Best First'.
Re^2: quoting/escaping file names
by famatte (Novice) on Sep 09, 2014 at 01:24 UTC
    hello. Take a look at this ..
    while(<>) { chomp; my $filename = $_; $filename =~ s/\$/\\\$/g; $filename =~ s/ /\ /g; $filename =~ s/\'/\\\'/g; print $filename ."\n"; my $exec = `md5sum $filename`; print $exec ."\n"; }
    find /tmp/ -type f | ./hash.pl <br> /tmp/File Wasn\'t found.txt <br> md5sum: /tmp/File: No such file or directory<br> md5sum: Wasn't: No such file or directory<br> md5sum: found.txt: No such file or directory<br> <br>
    Now if I quote $filename
    while(<>) { chomp; my $filename = $_; $filename =~ s/\$/\\\$/g; $filename =~ s/ /\ /g; $filename =~ s/\'/\\\'/g; print $filename ."\n"; my $exec = `md5sum '$filename'`; print $exec ."\n"; }
    find /tmp/ -type f | ./hash.pl /tmp/File Wasn\'t found.txt sh: Syntax error: Unterminated quoted string
    Any Ideias ? Thanks

      You want to quote the string properly for your shell. Most likely String::ShellQuote will do what you want.

        You want to quote the string properly for your shell.

        Perhaps. Or better, avoid the shell and use the list form of system or exec, as documented in perlipc. (Unless, of course, we're talking about Windows, where the quoting rules can differ from program to program because programs are invoked with a single argument string instead of a list of arguments.)

        Most likely String::ShellQuote will do what you want.

        No. It did not keep its promise in 2005, and despite a minor update, it still does not in 2014. It still lacks support for any shell except that one unnamed and unversioned shell the author tested against. It still lacks proper tests, and it still does not support Windows, DOS, OS/2, and any other OS that does not exclusively use a bourne shell.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      Avoid the shell.

      use warnings; use strict; use IPC::System::Simple 'capturex'; while (my $fn=<DATA>) { chomp($fn); $fn=~s/\\n/\n/g; # test filenames with newlines print "Filename: <<<$fn>>>\n"; # Method 1: capturex my $m1 = capturex('echo','-n',$fn); print "capturex: ", $m1 eq $fn ? "PASS" : "FAIL <<<$fn>>>", "\n"; # Method 2: piped open open my $pipe, '-|', 'echo', '-n', $fn or die $!; my $m2 = do { local $/; <$pipe> }; close $pipe or die $! ? $! : "\$?=$?"; print "open: ", $m2 eq $fn ? "PASS" : "FAIL <<<$fn>>>", "\n"; } __DATA__ $vaa it's not.txt /mnt1/$Recycle.Bin/S-1-5-21-3093161954-3198/$I7QM78L.pdf /tmp/File Wasn't found.txt ! @ # $ % ^ & * ( - + = { ] | \ : ; " ' < , . / ? ~ ` filename\nwith\newlines

      All PASS on my system (Linux).

      Avoid the shell and you avoid the need for shell quoteing

      #!/usr/bin/perl -- ## ## ## perltidy -olq -csc -csci=3 -cscl="sub : BEGIN END " -otr -opr -ce +-nibc -i=4 -pt=0 "-nsak=*" ## perltidy -olq -csc -csci=10 -cscl="sub : BEGIN END if " -otr -opr +-ce -nibc -i=4 -pt=0 "-nsak=*" ## perltidy -olq -csc -csci=10 -cscl="sub : BEGIN END if while " -otr + -opr -ce -nibc -i=4 -pt=0 "-nsak=*" #!/usr/bin/perl -- use strict; use warnings; use Digest; use Digest::MD5; use Path::Tiny qw/ path tempfile tempdir cwd /; use File::Find::Rule qw/ find rule /; Main( @ARGV ); exit( 0 ); sub Main { ## self test #~ warn mmd5external( __FILE__ ); #~ warn mmd5perl( __FILE__ ); #~ warn mmd5( __FILE__ ); #~ rule( 'file' )->exec( \&Famatte )->in( '/tmp' ); #~ find( 'file' => 'exec' => \&Famatte , in => [ '/tmp' ] ); rule( 'file' => 'exec' => \&Famatte, )->in( '/tmp' ); } ## end sub Main sub Famatte { my( $shortname, $path, $fullname ) = @_; RealFamatte( $fullname ); return !!0; # discard filename } ## end sub Famatte sub RealFamatte { my( $filename ) = @_; print mmd5( $filename ), "\t$filename\n"; } ## end sub RealFamatte sub mmd5 { goto &mmd5perl; #~ goto &mmd5external; } ## end sub mmd5 #~ sub mmd5external { #~ use File::Which qw/ which /; #~ use Capture::Tiny qw/ capture /; #~ my( @args ) = @_; #~ my $cmd = which('md5sum'); #~ my( $stdout, $stderr, $exit ) = capture { #~ system( $cmd, @args ); #~ }; #~ if( $exit ){ #~ warn "uhoh got error exit( $exit ) : $stderr "; #~ } else { #~ $stdout =~ s/\s+$//; ## "chomp" #~ return $stdout; #~ } #~ } sub mmd5perl { my $fh = path( shift )->openr_raw; my $ctx = Digest->new( 'MD5' ); $ctx->addfile( $fh ); return $ctx->hexdigest; } ## end sub mmd5perl

      perltidy, Digest, Digest::MD5, File::Find::Rule, Path::Tiny, File::Which, Capture::Tiny.

      Path::Tiny, find/rule