您认为在bash或Perl脚本中更改目录是否可以接受?或者应该不惜一切代价避免这样做?
此问题的最佳做法是什么?
答案 0 :(得分:26)
如果您不能控制整个过程,例如在子程序或模块中,那么问题更适用。在这些情况下,你想退出你输入的同一目录中的子程序,否则微妙的远距离动作会导致错误。
你可以手工制作......
use Cwd;
sub foo {
my $orig_cwd = cwd;
chdir "some/dir";
...do some work...
chdir $orig_cwd;
}
但这有问题。如果子例程提前返回或死亡(并且异常被捕获),则代码仍将在some/dir
中。此外,chdir
可能会失败,您必须记住检查每次使用。的Bleh。
幸运的是,有几个模块可以让这更容易。 File :: pushd是一个,但我更喜欢File::chdir。
use File::chdir;
sub foo {
local $CWD = 'some/dir';
...do some work...
}
File :: chdir将目录更改为分配给$CWD
。您可以对$CWD
进行本地化,以便在范围结束时重置,无论如何。它还会自动检查chdir
是否成功,否则抛出异常。有时它会在脚本中使用它,因为它非常方便。
答案 1 :(得分:16)
当前工作目录是执行shell的本地工作目录,所以你不能影响用户,除非他是“点”(在当前shell中运行它,而不是正常运行它创建一个新的shell进程)你的脚本
这样做的一个很好的方法是使用子shell,我经常在别名中使用。
alias build-product1='(cd $working-copy/delivery; mvn package;)'
paranthesis将确保从子shell执行命令,因此不会影响我的shell的工作目录。它也不会影响last-working-directory,所以 cd - ; 按预期工作。
答案 2 :(得分:4)
我不经常这样做,但有时它可以节省相当多的头痛。请确保如果更改目录,则始终更改回您开始的目录。否则,更改代码路径可能会将应用程序留在不应该的位置。
答案 3 :(得分:4)
对于Perl,您拥有CPAN的File::pushd模块,这使得本地更改工作目录非常优雅。引用概要:
use File::pushd;
chdir $ENV{HOME};
# change directory again for a limited scope
{
my $dir = pushd( '/tmp' );
# working directory changed to /tmp
}
# working directory has reverted to $ENV{HOME}
# tempd() is equivalent to pushd( File::Temp::tempdir )
{
my $dir = tempd();
}
# object stringifies naturally as an absolute path
{
my $dir = pushd( '/tmp' );
my $filename = File::Spec->catfile( $dir, "somefile.txt" );
# gives /tmp/somefile.txt
}
答案 4 :(得分:3)
我将在上面提到Schwern和Hugo的评论。请注意Schwern关于在意外退出时返回原始目录的警告。他提供了适当的Perl代码来处理它。我将指出shell(Bash,Korn,Bourne)陷阱命令。
陷阱“cd $ saved_dir”0
将在子shell退出时返回到saved_dir(如果你正在使用该文件)。
麦克
答案 5 :(得分:1)
还要考虑Unix和Windows有内置目录堆栈:pushd and popd。它非常易于使用。
答案 6 :(得分:0)
尝试使用完全量化的路径是否完全可行,而不是对您当前所在的目录做出任何假设? e.g。
use FileHandle;
use FindBin qw($Bin);
# ...
my $file = new FileHandle("< $Bin/somefile");
而不是
use FileHandle;
# ...
my $file = new FileHandle("< somefile");
从长远来看,这可能会更容易,因为您不必担心发生奇怪的事情(您的脚本在将当前工作目录恢复到原来的状态之前死亡或被杀死),并且相当可能更便携。