从 perl 向系统命令传递参数
Passing arguments to system commands from perl
我正在编写一个使用一些 ImageMagick 命令的 perl 脚本,特别是识别。相关代码在这里:
my $height = system("identify -format %h $curPic");
my $width = system("identify -format %w $curPic");
当我 运行 整个脚本时,它挂在这些行上,这是输出:
identify: unable to open image 'if0W211.jpg': No such file or directory @ error/blob.c/OpenBlob/3323
identify: unable to open image 'if0W211.jpg': No such file or directory @ error/blob.c/OpenBlob/3323
起初,问题与 ImageMagick 没有正确的格式委托来处理 jpg 图像有关,但在修复该问题后,我仍然遇到此错误。我找不到与 "error/blob.c/OpenBlob/3323" 相关的任何错误文档。在编写了一些测试代码以查看可能是什么问题之后,我想我已经确定它与 perl 将参数传递给系统命令的方式有关,因为当我在终端中编写该系统命令 identify -format %h xxxx.jpg
,它工作得很好。我还注意到,当我 print "$curPic\n
时,256 会在打印过程中添加到文件名前。我不知道为什么会这样。
作为参考,以下是我收集文件名的方式:
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
这是完整的脚本:
#!/usr/bin/perl -w
use strict;
use diagnostics;
use File::Copy;
my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";
#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
my $height = system("identify -format %h $curPic");
my $width = system("identify -format %w $curPic");
#move those that are vertically oriented to a different folder
if ($height >= ($width*0.8)) {
move($curPic, $oriFolder//$curPic) or die "The ori move operation failed for image $curPic: $!";
print "$curPic was not approved because of its orientation.";
next;
}
#move those that are low res to a third folder
elsif (($height < 1080) | ($width < 1920)) {
move($curPic, $resFolder//$curPic) or die "The res move operation failed for image $curPic: $!";
print "$curPic was not approved because of its resolution.";
next;
}
print "$curPic is approved as a desktop background";
}
编辑:
我正在切换到推荐的 Image::Size 库,所以这是我更新的脚本。它工作了一段时间,给了我想要的输出,但突然中断并说变量未初始化。 "Use of uninitialized variable..." $height 和 $width 有一个错误,但在大约 20 次成功迭代后它们再次发生。如果我 运行 脚本多次背靠背,它似乎会有所不同。
#!/usr/bin/perl -w
use strict;
use diagnostics;
use File::Copy;
use Image::Size;
my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";
my $height = 0;
my $width = 0;
#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
($width, $height) = imgsize("$folder/$curPic");
#move those that are vertically oriented to a different folder
if ($height >= ($width*0.8)) {
move("$folder/$curPic", "$oriFolder/$curPic") or die "The ori move operation failed for image $curPic: $!";
print "$curPic was not approved because of its orientation.\n";
next;
}
#move those that are low res to a third folder
elsif (($height < 1080) | ($width < 1920)) {
move("$folder/$curPic", "$resFolder/$curPic") or die "The res move operation failed for image $curPic: $!";
print "$curPic was not approved because of its resolution.\n";
next;
}
print "$curPic is approved as a desktop background.\n";
}
如消息所述,您正在将路径传递给一个不存在的文件。而不是传递
if0W211.jpg
你应该过去了
/media/sf_Pictures_from_Reddit/if0W211.jpg
这仍然会给您带来以下问题:
- 注入错误
- 路径可能被误解为一个选项。
- 缺乏错误处理
- 缺少对程序输出的捕获。
- 重复执行外部进程。
所有这些都可以通过使用 Image::Size 来解决。
但是如果你坚持使用identify
,
use IPC::System::Simple qw( capturex );
my $dimensions = eval { capturex("identify", "-format", "%h,%w", "--", "$folder/$curPic") }
or do {
warn("Can't determine the dimensions of \"$folder/$curPic\": $@");
next;
};
my ($height, $width) = $dimensions =~ /^(\d+),(\d+)$/
or do {
warn("Can't determine the dimensions of \"$folder/$curPic\": Unexpected output from \"identify\": $dimensions\n");
next;
};
如果您的 identify
不支持 --
(或者即使支持),您可以更换
"--", "$folder/$curPic"
和
"$folder/$curPic" =~ s{^-}{./-}r
就目前而言,您正在为每张图像创建两个新进程(一个用于识别宽度,另一个用于识别高度),因此如果您有大量图像,这可能会给您的系统带来相当大的负载图片。
作为替代方案,您可以只调用一个 identify
进程并将所有图像名称传递给它,如下所示:
identify -format "%w:%h:%f\n" *jpg
示例输出
2000:1200:ok.jpg
1200:2000:toolow2.jpg
1000:500:vert.jpg
然后您可以使用 bash
或 Perl
:
解析它
#!/bin/bash
VERT="/tmp"
TOOLOW="/tmp"
identify -format "%w:%h:%f\n" *jpg |
while IFS=: read w h name; do
echo "DEBUG: $name, $w, $h"
[[ $h -gt $(( (8*w)/10 )) ]] && { mv "$name" "$VERT"; >&2 echo "Too tall: $name"; continue; }
[[ ($h -lt 1080) || ($w -lt 1920) ]] && { mv "$name" "$TOOLOW"; >&2 echo "Low res: $name"; continue; }
echo "$name approved"
done
这是适合我的目的的最终脚本。我添加了定义检查和非零检查,以确保变量在继续之前接收到正确的输入。
#!/usr/bin/perl -w
use strict;
use diagnostics;
use File::Copy;
use Image::Size;
my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";
my $height = 0;
my $width = 0;
#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
($width, $height) = imgsize("$folder/$curPic") or die "Couldn't get the image dimensions for $curPic: $!";
if($curPic eq "." || $curPic eq ".."){ next;}
if((defined $height) & (defined $width)){
if(($height != 0) & ($width != 0)) {
print "File: $curPic\nHeight: $height\nWidth: $width\n";
#sleep(0.5);
#move those that are vertically oriented to a different folder
if($height >= ($width*0.8)) {
move("$folder/$curPic", "$oriFolder/$curPic") or die "The ori move operation failed for $curPic: $!";
print "$curPic was not approved because of its orientation.\n\n";
next;
}
#move those that are low res to a third folder
elsif(($height < 1080) | ($width < 1920)) {
move("$folder/$curPic", "$resFolder/$curPic") or die "The res move operation failed for $curPic: $!";
print "$curPic was not approved because of its resolution.\n\n";
next;
}
print "$curPic is approved as a desktop background.\n\n";
$height = 0;
$width = 0;
}
else{
print "Variables failed to initialize.\n\n";
}
}
else{
print "Variables are undefined.\n\n";
}
}
我正在编写一个使用一些 ImageMagick 命令的 perl 脚本,特别是识别。相关代码在这里:
my $height = system("identify -format %h $curPic");
my $width = system("identify -format %w $curPic");
当我 运行 整个脚本时,它挂在这些行上,这是输出:
identify: unable to open image 'if0W211.jpg': No such file or directory @ error/blob.c/OpenBlob/3323
identify: unable to open image 'if0W211.jpg': No such file or directory @ error/blob.c/OpenBlob/3323
起初,问题与 ImageMagick 没有正确的格式委托来处理 jpg 图像有关,但在修复该问题后,我仍然遇到此错误。我找不到与 "error/blob.c/OpenBlob/3323" 相关的任何错误文档。在编写了一些测试代码以查看可能是什么问题之后,我想我已经确定它与 perl 将参数传递给系统命令的方式有关,因为当我在终端中编写该系统命令 identify -format %h xxxx.jpg
,它工作得很好。我还注意到,当我 print "$curPic\n
时,256 会在打印过程中添加到文件名前。我不知道为什么会这样。
作为参考,以下是我收集文件名的方式:
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
这是完整的脚本:
#!/usr/bin/perl -w
use strict;
use diagnostics;
use File::Copy;
my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";
#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
my $height = system("identify -format %h $curPic");
my $width = system("identify -format %w $curPic");
#move those that are vertically oriented to a different folder
if ($height >= ($width*0.8)) {
move($curPic, $oriFolder//$curPic) or die "The ori move operation failed for image $curPic: $!";
print "$curPic was not approved because of its orientation.";
next;
}
#move those that are low res to a third folder
elsif (($height < 1080) | ($width < 1920)) {
move($curPic, $resFolder//$curPic) or die "The res move operation failed for image $curPic: $!";
print "$curPic was not approved because of its resolution.";
next;
}
print "$curPic is approved as a desktop background";
}
编辑: 我正在切换到推荐的 Image::Size 库,所以这是我更新的脚本。它工作了一段时间,给了我想要的输出,但突然中断并说变量未初始化。 "Use of uninitialized variable..." $height 和 $width 有一个错误,但在大约 20 次成功迭代后它们再次发生。如果我 运行 脚本多次背靠背,它似乎会有所不同。
#!/usr/bin/perl -w
use strict;
use diagnostics;
use File::Copy;
use Image::Size;
my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";
my $height = 0;
my $width = 0;
#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
($width, $height) = imgsize("$folder/$curPic");
#move those that are vertically oriented to a different folder
if ($height >= ($width*0.8)) {
move("$folder/$curPic", "$oriFolder/$curPic") or die "The ori move operation failed for image $curPic: $!";
print "$curPic was not approved because of its orientation.\n";
next;
}
#move those that are low res to a third folder
elsif (($height < 1080) | ($width < 1920)) {
move("$folder/$curPic", "$resFolder/$curPic") or die "The res move operation failed for image $curPic: $!";
print "$curPic was not approved because of its resolution.\n";
next;
}
print "$curPic is approved as a desktop background.\n";
}
如消息所述,您正在将路径传递给一个不存在的文件。而不是传递
if0W211.jpg
你应该过去了
/media/sf_Pictures_from_Reddit/if0W211.jpg
这仍然会给您带来以下问题:
- 注入错误
- 路径可能被误解为一个选项。
- 缺乏错误处理
- 缺少对程序输出的捕获。
- 重复执行外部进程。
所有这些都可以通过使用 Image::Size 来解决。
但是如果你坚持使用identify
,
use IPC::System::Simple qw( capturex );
my $dimensions = eval { capturex("identify", "-format", "%h,%w", "--", "$folder/$curPic") }
or do {
warn("Can't determine the dimensions of \"$folder/$curPic\": $@");
next;
};
my ($height, $width) = $dimensions =~ /^(\d+),(\d+)$/
or do {
warn("Can't determine the dimensions of \"$folder/$curPic\": Unexpected output from \"identify\": $dimensions\n");
next;
};
如果您的 identify
不支持 --
(或者即使支持),您可以更换
"--", "$folder/$curPic"
和
"$folder/$curPic" =~ s{^-}{./-}r
就目前而言,您正在为每张图像创建两个新进程(一个用于识别宽度,另一个用于识别高度),因此如果您有大量图像,这可能会给您的系统带来相当大的负载图片。
作为替代方案,您可以只调用一个 identify
进程并将所有图像名称传递给它,如下所示:
identify -format "%w:%h:%f\n" *jpg
示例输出
2000:1200:ok.jpg
1200:2000:toolow2.jpg
1000:500:vert.jpg
然后您可以使用 bash
或 Perl
:
#!/bin/bash
VERT="/tmp"
TOOLOW="/tmp"
identify -format "%w:%h:%f\n" *jpg |
while IFS=: read w h name; do
echo "DEBUG: $name, $w, $h"
[[ $h -gt $(( (8*w)/10 )) ]] && { mv "$name" "$VERT"; >&2 echo "Too tall: $name"; continue; }
[[ ($h -lt 1080) || ($w -lt 1920) ]] && { mv "$name" "$TOOLOW"; >&2 echo "Low res: $name"; continue; }
echo "$name approved"
done
这是适合我的目的的最终脚本。我添加了定义检查和非零检查,以确保变量在继续之前接收到正确的输入。
#!/usr/bin/perl -w
use strict;
use diagnostics;
use File::Copy;
use Image::Size;
my $folder = "/media/sf_Pictures_from_Reddit";
my $oriFolder = "/media/sf_WrongOrientation";
my $resFolder = "/media/sf_LowRes";
my $height = 0;
my $width = 0;
#Collect all the files
opendir DIR, $folder or die "Cannot open directory: $!";
my @files = readdir(DIR);
closedir(DIR);
#Iterate through each file and check its orientation and resolution
foreach my $curPic (@files) {
($width, $height) = imgsize("$folder/$curPic") or die "Couldn't get the image dimensions for $curPic: $!";
if($curPic eq "." || $curPic eq ".."){ next;}
if((defined $height) & (defined $width)){
if(($height != 0) & ($width != 0)) {
print "File: $curPic\nHeight: $height\nWidth: $width\n";
#sleep(0.5);
#move those that are vertically oriented to a different folder
if($height >= ($width*0.8)) {
move("$folder/$curPic", "$oriFolder/$curPic") or die "The ori move operation failed for $curPic: $!";
print "$curPic was not approved because of its orientation.\n\n";
next;
}
#move those that are low res to a third folder
elsif(($height < 1080) | ($width < 1920)) {
move("$folder/$curPic", "$resFolder/$curPic") or die "The res move operation failed for $curPic: $!";
print "$curPic was not approved because of its resolution.\n\n";
next;
}
print "$curPic is approved as a desktop background.\n\n";
$height = 0;
$width = 0;
}
else{
print "Variables failed to initialize.\n\n";
}
}
else{
print "Variables are undefined.\n\n";
}
}