Perl 什么';在脚本中更改工作目录的最佳实践是什么?
您认为在bash或Perl脚本中更改目录是可以接受的吗?还是应该不惜一切代价避免这样做Perl 什么';在脚本中更改工作目录的最佳实践是什么?,perl,bash,shell,zsh,Perl,Bash,Shell,Zsh,您认为在bash或Perl脚本中更改目录是可以接受的吗?还是应该不惜一切代价避免这样做 解决这个问题的最佳做法是什么?我不经常这样做,但有时这样做可以省去不少麻烦。只要确保如果您更改了目录,您总是会更改回您开始使用的目录。否则,更改代码路径可能会将应用程序留在不应该在的地方。当前工作目录是正在执行的shell的本地目录,因此您不能影响用户,除非他正在“点播”(在当前shell中运行它,而不是在正常情况下运行它创建新的shell进程)您的脚本 一个很好的方法是使用子shell,我经常在别名中这样做
解决这个问题的最佳做法是什么?我不经常这样做,但有时这样做可以省去不少麻烦。只要确保如果您更改了目录,您总是会更改回您开始使用的目录。否则,更改代码路径可能会将应用程序留在不应该在的地方。当前工作目录是正在执行的shell的本地目录,因此您不能影响用户,除非他正在“点播”(在当前shell中运行它,而不是在正常情况下运行它创建新的shell进程)您的脚本 一个很好的方法是使用子shell,我经常在别名中这样做
alias build-product1='(cd $working-copy/delivery; mvn package;)'
这个脚本将确保命令是从一个子shell执行的,因此不会影响shell的工作目录。它也不会影响最后一个工作目录,因此cd-按预期工作。还要考虑Unix和Windows具有内置目录堆栈:。它非常容易使用。正如Hugo所说,您无法影响父进程的cwd,因此没有问题 更适用的问题是,如果您不控制整个过程,比如在子例程或模块中。在这些情况下,您希望在输入的同一目录中退出子例程,否则会发生细微的移动,从而导致错误 你可以用手把这个拿出来
use Cwd;
sub foo {
my $orig_cwd = cwd;
chdir "some/dir";
...do some work...
chdir $orig_cwd;
}
但这也有问题。如果子例程提前返回或终止(异常被捕获),则代码仍将位于some/dir
。而且,chdir
s可能会失败,您必须记住检查每次使用。呜呜
幸运的是,有几个模块可以让这更容易。文件::pushd是其中之一,但我更喜欢
chdir将目录更改为分配给$CWD
。您可以本地化$CWD
,这样无论发生什么情况,它都会在范围结束时重置。它还自动检查chdir
是否成功,否则抛出异常。有时它在脚本中使用它,因为它非常方便。对于Perl,您有来自CPAN的模块,这使得在本地更改工作目录非常优雅。引述大纲:
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
}
我将支持上面Schwern和Hugo的评论。请注意Schwern关于在意外退出时返回原始目录的警告。他提供了适当的Perl代码来处理这个问题。我将指出shell(Bash、Korn、Bourne)陷阱命令 陷阱“cd$saved_dir”0 将在子shell退出时返回到保存的_dir(如果正在删除文件)
mike尝试使用完全量化的路径,而不假设您当前所在的目录是否可行?e、 g
use FileHandle;
use FindBin qw($Bin);
# ...
my $file = new FileHandle("< $Bin/somefile");
使用文件句柄;
在qw中使用FindBin($Bin);
# ...
my$file=newfilehandle(“<$Bin/somefile”);
而不是
use FileHandle;
# ...
my $file = new FileHandle("< somefile");
使用文件句柄;
# ...
my$file=newfilehandle(“
从长远来看,这可能会更容易,因为您不必担心发生奇怪的事情(在将当前工作目录放回原来的位置之前,您的脚本将死亡或被杀死),而且可能更易于移植。在Unix衍生产品上不可以。是的,如果您将“应用程序”作为“相同的可执行文件,但不同的功能”-您不能更改父进程的cwd。对“应用程序”一词的解释是什么“会让你认为???@Tanktalus有我的意思,即使我显然解释得很糟糕。在应用程序中,如果您多次更改目录并更改代码路径,应用程序的不同部分可能需要不同的起始目录点。当您的代码位于处理多个请求的web应用程序中时,这一点很重要。如果您更改了目录但未能更改回目录,则该子级处理的下一个请求将位于意外的位置。在我的例子中,插件代码找不到会话目录,因为它使用的是相对路径。我不明白这个问题。有人怎么知道你的脚本把一张cd放到了一个新的目录中?目前的答案是从“它的语法有效,不影响父shell,所以没问题”的角度来看的。我看到了这个问题的另一部分,类似于“脚本的cd’ing是丑陋的编码风格吗,类似于非常长的Python行或选择不当的变量名——这是可以做到的,但却是最好避免的做法”。我认为File::chdir不是一个核心模块?如果你想坚持核心模块,Hugo的方法是下一个最好的选择吗?@SSilk Hugo的技术是完全不同的,更适用于运行其他命令的构建脚本。Mine适用于程序和库的内部。两者都试图完全隔离正在更改的目录,以免影响其他任何内容。
use FileHandle;
# ...
my $file = new FileHandle("< somefile");