Reputation: 1142
I'm trying to download ruby gems listed in several example rails projects I downloaded via bundle install
with the latest version of ruby installed through RVM, and I'm following the directions here to properly downloads the gems listed in the bundler files. I thought I'd speed up the process with this perl script: (Not quite comfortable with bash yet):
#!/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 ..`;
}
}
error is:
copy: No such file or directory
The file clearly exists these projects are presumably created with rails <name>
command. Why would this happen and how do I fix it?
Upvotes: 0
Views: 1226
Reputation: 24063
When you invoke an external command with system
or backticks, you spawn a new process. That process gets its own environment, which is not shared with the parent process or with other children:
system('pwd'); # /foo
system('cd "/bar"');
system('pwd'); # still /foo
(Note that if you're not actually storing the output of a command, it's preferable to use system
instead of backticks.)
This means that when you `cd "$dir"`
, your Perl script's working directory isn't changing. To fix, use native Perl commands instead of invoking shell commands.
Here's a rough example (untested):
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: $!";
}
}
Upvotes: 4