Search code examples
shellperl

Executing shell command containing quotations in Perl


I have method that is listing files/folders to be deleted on unix. Then I delete it with the code:

for my $line (@linesFiles) {
    my $command = "rm '$line';"; # or my $command = "rmdir '$line';";
    my ($stdout, $stderr) = capture {
        system ($command);
        };      
    }

Mots of the time it works, but sometimes files/folders have incorrect names containing quotation marks, like some\folder\incorrect'name or some\folder\incorrect"name. I would need to delete those files/folder as well.

But using my code I'm getting EOF error or that file/folder does not exist error. When using q or qq, the quotation marks were removed from the filename resulting in file/folder does not exist error.

Would anybody help me with how to modify the code, so it would be able to delete files/folders containing any potentially dangerous (at least for this case) characters like " ' $ { } ?


Solution

  • To build a shell command, you can use String::ShellQuote (or Win32::ShellQuote).

    use String::ShellQuote qw( shell_quote );
    
    my $shell_cmd = shell_quote( "rm", "--", $qfn );
    system( $shell_cmd );
    die( "Couldn't launch shell to unlink \"$qfn\": $!\n" )                             if $? == -1;
    die( "Shell killed by signal ".( $? & 0x7F )." while trying to unlink \"$qfn\"\n" ) if $? & 0x7F;
    die( "Shell exited with error ".( $? >> 8 )." while trying to unlink \"$qfn\"\n" )  if $? >> 8;
    
    

    But why involve a shell at all? You can use the multi-argument form of system.

    system( "rm", "--", $qfn );
    die( "Couldn't launch rm to unlink \"$qfn\": $!\n" )                             if $? == -1;
    die( "rm killed by signal ".( $? & 0x7F )." while trying to unlink \"$qfn\"\n" ) if $? & 0x7F;
    die( "rm exited with error ".( $? >> 8 )." while trying to unlink \"$qfn\"\n" )  if $? >> 8;
    

    But why involve an external tool at all. You can use unlink to delete files.

    unlink( $qfn )
       or die( "Can't unlink \"$qfn\": $!\n" );