perl:File :: Copy:读取现有文件时没有此类文件或目录错误

时间:2015-01-26 22:46:32

标签: perl

我正在尝试下载我通过bundle install下载的几个示例rails项目中列出的ruby gem,其中包含通过RVM安装的最新版本的ruby,我按照here的说明正确下载捆绑文件中列出的宝石。我以为我会用这个perl脚本加快这个过程:(对bash不太满意):

#!/usr/bin/perl
use File::Copy qq(copy);

use strict;
use warnings;

my @files = `ls`;
foreach my $dir (@files)
{
    chomp $dir;
    if( -d $dir)
    {
        print "\n\n\tabout to enter $dir\n\n\n";
        print `cd "$dir"`;
        system("echo \"2.2.0\" > .ruby-version");
        system("echo \"$dir\" > .ruby-gemset");
        copy("Gemfile", "tmp.save") or die "copy: $!\n";
        open(RD,"<tmp.save") or die "$dir: tmp.save: $!\n";
        open(WR,">Gemfile") or die "$dir: Gemfile: $!\n";
        print WR <RD>;
        print WR "\n";
        print WR "ruby \'2.2.0\'";
        print WR "\n\n";
        while(<RD>) { print WR $_; print WR "\n"; }
        close(RD); close(WR);
        print `cd ..`; 
        print `cd "$dir"`;
        print `bundle install`;
        print `cd ..`;
    }
}

错误是:

copy: No such file or directory

该文件显然存在这些项目可能是使用rails <name>命令创建的。为什么会发生这种情况?如何解决?

1 个答案:

答案 0 :(得分:4)

当您使用system或反引号调用外部命令时,会生成一个新进程。该进程获得自己的环境,不与父进程或其他子进程共享:

system('pwd'); # /foo
system('cd "/bar"');
system('pwd'); # still /foo

(请注意,如果您实际上并未存储命令的输出,则最好使用system而不是反引号。)

这意味着当您`cd "$dir"`时,您的Perl脚本的工作目录不会更改。要修复,请使用本机Perl命令,而不是调用shell命令。

这是一个粗略的例子(未经测试):

use strict;
use warnings;

use File::Copy;

my $parent_dir = 'foo';

opendir my $dh, $parent_dir or die "opendir failed on '$parent_dir': $!";

my @subdirs = map { "$parent_dir/$_" }
              grep { $_ !~ /^\.\.?$/ && -d "$parent_dir/$_" } readdir $dh;

foreach my $subdir (@subdirs) {
    my $source = "$subdir/Gemfile";
    my $target = "$subdir/tmp.save";

    if (-f $source) {
        copy $source, $target or die "copy failed: $!";
    }
}