in reply to Re: quoting/escaping file names
in thread quoting/escaping file names

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

Replies are listed 'Best First'.
Re^3: quoting/escaping file names
by Corion (Patriarch) on Sep 09, 2014 at 07:11 UTC

    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". ;-)

        The fact that it only supports one family of shells is not a bug.

Re^3: quoting/escaping file names
by Anonymous Monk on Sep 09, 2014 at 08:04 UTC

    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).

Re^3: quoting/escaping file names (Path::Tiny find/rule Digest::MD5 )
by Anonymous Monk on Sep 09, 2014 at 08:18 UTC

    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