如何在路径包含空格的文件上使用`diff`

时间:2016-11-22 15:48:50

标签: linux perl shell unix

我试图找到文件之间的差异,但文件名和目录名称包含空格。我试图在Perl脚本中执行命令。

diff /home/users/feroz/logs/back_up20161112/Security File/General Security.csv /home/users/feroz/logs/back_up20161113/Security File/General Security.csv

的Perl

open( my $FH, '>', $logfile ) or die "Cannot open the file '$logfile' $!";

foreach $filename ( keys %filenames ) {

    $old_file = $parent_directory . $previous_date . $search_directory . "$filenames{$filename}";
    $new_file = $parent_directory . $current_date . $search_directory . "$filenames{$filename}";

    if ( !-e $old_file ) {

        #print ("\nFile does not exist in previos date backup");

        print $FH "\nERROR:'$old_file' ---- does not exist in the backup directory ";
    }
    elsif ( !-e $new_file ) {

        #print ("\n The file does not exist in current directory");

        print $FH "\nERROR:'$new_file' --- does not exist in the present directory ";
    }
    else {

        # print $FH "\nDifference between the files $filenames{$filename} of  $previous_date and $current_date ";

        my $cmd = 'diff $old_file $new_file| xargs -0';
        open( my $OH, '|-', $cmd ) or die "Failed to read the output";
        while ( <OH> ) {
            print $FH "$_";
        }
        close $OH;
    }
}

4 个答案:

答案 0 :(得分:3)

要绝对安全,请使用ShellQuote

use String::ShellQuote;

my $old_file2 = shell_quote($old_file);
my $new_file2 = shell_quote($new_file);
`diff $old_file2 $new_file2`;

答案 1 :(得分:2)

在带外传递参数以避免需要对它们进行shell引用,而不是将它们插入到由shell作为脚本解析的字符串中。将文件名作为文字文本替换为脚本会产生shell injection attacks的暴露 - shell脚本等同于称为SQL injection的数据库安全漏洞系列。

根本没有任何外壳

xargs -0的管道似乎没有任何用处。消除它允许在没有任何shell的情况下运行它:

open(my $fh, "-|", "diff", $old_file, $new_file)

Shell参数从脚本文本传出带外

如果你确实想要调用shell,那么安全的做法是使脚本文本保持审计常量,并让它从传递给shell或环境的argv列表中检索参数。

# Putting $1 and $2 in double quotes ensures that the shell treats contents as literal
# the "_" is used for $0 in the shell.
$shell_script='diff "$1" "$2" | xargs -0'
open(my $fh, "-|",
  "sh", "-c", $shell_script,
  "_", $old_file, $new_file);

答案 2 :(得分:1)

你可以

  1. 将空白路径段放在引号

    diff /home/users/feroz/logs/back_up20161112/"Security File"/General Security.csv /home/users/feroz/logs/back_up20161113/"Security File"/General Security.csv
    
  2. 或逃避空白

    diff /home/users/feroz/logs/back_up20161112/Security\ File/General Security.csv /home/users/feroz/logs/back_up20161113/Security\ File/General Security.csv`
    

答案 3 :(得分:1)

感谢您展示您的Perl代码

单引号不进行插值,因此会将字符串$old_file$new_file传递给命令而不是那些变量&#39;内容。然后shell将尝试将它们解释为shell变量

我建议你写这个

my $cmd = qq{diff '$old_file' '$new_file' | xargs -0};
open( my $OH, '-|', $cmd ) or die "Failed to read the output";

这将在命令字符串周围使用双引号qq{...}),以便插入变量。文件路径周围有单引号,表示shell应将它们视为单个字符串

如果您的文件路径可能包含单引号,那么这不会起作用,但这非常不寻常