我试图找到文件之间的差异,但文件名和目录名称包含空格。我试图在Perl脚本中执行命令。
diff /home/users/feroz/logs/back_up20161112/Security File/General Security.csv /home/users/feroz/logs/back_up20161113/Security File/General Security.csv
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;
}
}
答案 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或环境的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)
你可以
将空白路径段放在引号
中diff /home/users/feroz/logs/back_up20161112/"Security File"/General Security.csv /home/users/feroz/logs/back_up20161113/"Security File"/General Security.csv
或逃避空白
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应将它们视为单个字符串
如果您的文件路径可能包含单引号,那么这不会起作用,但这非常不寻常