Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 什么';在脚本中更改工作目录的最佳实践是什么?_Perl_Bash_Shell_Zsh - Fatal编程技术网

Perl 什么';在脚本中更改工作目录的最佳实践是什么?

Perl 什么';在脚本中更改工作目录的最佳实践是什么?,perl,bash,shell,zsh,Perl,Bash,Shell,Zsh,您认为在bash或Perl脚本中更改目录是可以接受的吗?还是应该不惜一切代价避免这样做 解决这个问题的最佳做法是什么?我不经常这样做,但有时这样做可以省去不少麻烦。只要确保如果您更改了目录,您总是会更改回您开始使用的目录。否则,更改代码路径可能会将应用程序留在不应该在的地方。当前工作目录是正在执行的shell的本地目录,因此您不能影响用户,除非他正在“点播”(在当前shell中运行它,而不是在正常情况下运行它创建新的shell进程)您的脚本 一个很好的方法是使用子shell,我经常在别名中这样做

您认为在bash或Perl脚本中更改目录是可以接受的吗?还是应该不惜一切代价避免这样做


解决这个问题的最佳做法是什么?

我不经常这样做,但有时这样做可以省去不少麻烦。只要确保如果您更改了目录,您总是会更改回您开始使用的目录。否则,更改代码路径可能会将应用程序留在不应该在的地方。

当前工作目录是正在执行的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");