在perl脚本中查找命令问题

时间:2014-04-24 00:01:28

标签: perl

我正在编写一个脚本,它将创建一个新的tar文件,其中只包含在创建上一个tar.gz文件之后创建的文件。

my $path_to_logs = "/home/myscripts/";
my $FNAME= `ls -t *.tar.gz | head -n1`;
my $FILENAME = $path_to_logs.$FNAME;
chomp ($FILENAME);

if (-e $FILENAME){
     my $changed= `find . -name '*.log'  -newer $FILENAME`;
    chomp $changed;
    $command = "tar -cvzT ". $changed." -f deleteme-$(date +%Y-%m-%d-%H-%M-%S).tar.gz";
    chomp $command;
    print $command;
    }

然而,$ out命令的outout显示每个查找结果都在一个新行上,所以我不会使用连接的tar命令。知道为什么吗?

感谢。

3 个答案:

答案 0 :(得分:0)

只需将find的输出转换为一行:

 my $changed= `find . -name '*.log'  -newer $FILENAME`;
chomp $changed;

$changed =~ s/\n/ /g;

$command = "tar -cvzT -f deleteme-$(date +%Y-%m-%d-%H-%M-%S).tar.gz " . $changed;
通常,通常,减少对操作系统特定功能的依赖通常会更好。您可以使用不太费力的方法复制您在perl中对操作系统进行shell操作的所有命令:

use strict;
use warnings;
use autodie;

use File::Find::Rule;
use File::stat;
use Time::Piece;

my $path_to_logs = "/home/myscripts/";

my ($FILENAME) = sort {
    stat($a)->mtime <=> stat($b)->mtime
} glob('/home/myscripts/*.tar.gz');

if (-e $FILENAME){
    my $modified = stat($FILENAME)->mtime;

    my @files = File::Find::Rule->file()
                                ->name('*.log')
                                ->modified(">$modified")
                                ->in('.');

    my $datenow = localtime->strftime('%Y-%m-%d-%H-%M-%S');

    my $command = "tar -cvzT -f deleteme-${datenow}.tar.gz ". join(' ', @files);

您甚至可以使用Archive::Tar代替/bin/tar,但这可能会影响性能。

然而,无论如何,这些简单的更改使您的脚本更加便携,并且不需要额外的代码。

答案 1 :(得分:0)

如何解决您的直接问题:

my $find_cmd = "find . -name '*.log' -newer $filename";
open my $in, '-|', $find_cmd or die "Couldn't run command. $!\n";
while(<$in>) {
  chomp;
  print "Do something with file: $_\n";
}

如果你需要一行中的文件你可以创建一个变量并连接它们或者其他什么,我只是想告诉你一个更好的方法来调用系统命令(如果你可以直接调用命令会更好没有shell扩展,但你依赖于那里的shell扩展)。

从长远来看,你可能想学习如何使用perl自己的find / wanted例程以及如何进行dir globbing而不必过多地依赖系统。

答案 2 :(得分:0)

无论如何,在Perl中做这件事并没有多大意义。无论使用哪种包装语言,将find输出直接传递给tar都会更简单,更健壮,tar知道如何处理它。

无论如何,您使用-T&#39; FNAME选项是错误的。它需要一个包含文件名的文件名,每行一个,而不是文件名列表。

此外,您的/home/myscripts包含当前目录中的最新文件,其中显然意图是在$(date ...)中找到最新文件。

最后,#!/bin/sh path_to_logs = "/home/myscripts/" FNAME=$(cd "$path_to_logs"; ls -t *.tar.gz | head -n1) FILENAME = "$path_to_logs/$FNAME" if [ -e "$FILENAME" ]; then find . -name '*.log' -newer "$FILENAME" | tar -c -v -z -T - -f deleteme-$(date +%Y-%m-%d-%H-%M-%S).tar.gz fi 插值不会被Perl插值,但是如果将它(返回?)转换为shell脚本,则会很简单。

{{1}}