Какова лучшая практика для изменения рабочих каталогов в сценариях?

Я согласен, что это ошибка в реализации findloc () в Intel Fortran. Я создал отчет об ошибках Intel для наших разработчиков.

11
задан brian d foy 27 October 2008 в 20:11
поделиться

7 ответов

Текущий рабочий каталог локален для выполняющейся оболочки, таким образом, Вы не можете влиять на пользователя, если он не "отмечает точкой" (выполнение его в текущей оболочке, в противоположность выполнению его обычно создание нового процесса оболочки) Ваш сценарий.

Очень хороший способ сделать это состоит в том, чтобы использовать подоболочки, которые я часто делаю в псевдонимах.

alias build-product1='(cd $working-copy/delivery; mvn package;)'

Круглая скобка удостоверится, что команда выполняется от подоболочки и таким образом не будет влиять на рабочий каталог моей оболочки. Также это не будет влиять на последний рабочий каталог, таким образом, CD-; работы как ожидалось.

16
ответ дан 3 December 2019 в 00:53
поделиться

Как сказанный Hugo, Вы не можете произвести cwd своего родительского процесса, таким образом, нет никакой проблемы.

То, где вопрос более применим, - то, если Вы не управляете целым процессом, как в подпрограмме или модуле. В тех случаях Вы хотите выйти из подпрограммы в том же каталоге, как Вы вошли, в других отношениях тонкий action-at-a-distance закрадывается который ошибки причин.

Вы можете к этому вручную...

use Cwd;
sub foo {
    my $orig_cwd = cwd;
    chdir "some/dir";

    ...do some work...

    chdir $orig_cwd;
}

но это имеет проблемы. Если подпрограмма возвратится рано или умрет (и исключение захватывается), то Ваш код все еще будет в some/dir. Кроме того, chdirs мог бы перестать работать, и необходимо не забыть проверять каждое использование. Bleh.

К счастью, существует пара модулей для создания этого легче. File::pushd один, но я предпочитаю File::chdir.

use File::chdir;
sub foo {
    local $CWD = 'some/dir';

    ...do some work...
}

File::chdir превращает изменяющиеся каталоги в присвоение $CWD. И можно локализовать $CWD таким образом, это сбросит в конце Вашего объема, несмотря ни на что. Это также автоматически проверяет если chdir следует и выдает исключение иначе. Иногда это использует его в сценариях, потому что это настолько удобно.

26
ответ дан 3 December 2019 в 00:53
поделиться

Я часто не делаю этого, но иногда это может сохранить довольно мало головной боли. Просто убедитесь, что при изменении каталогов Вы всегда возвращаетесь к каталогу, с которого Вы запустили. Иначе изменение путей выполнения кода могло оставить приложение где-нибудь, это не должно быть.

4
ответ дан 3 December 2019 в 00:53
поделиться

Я буду комментарии второго Schwern и Hugo выше. Отметьте осторожность Schwern в отношении возврата исходному каталогу в случае неожиданного выхода. Он предоставил соответствующий код Perl для обработки этого. Я укажу на оболочку (Bash, Korn, Граница) команда прерывания.

захватите "$saved_dir CD" 0

возвратится к saved_dir на выходе подоболочки (если Вы будете.'ing файл).

микрофон

3
ответ дан 3 December 2019 в 00:53
поделиться

Для Perl у Вас есть модуль File::pushd от 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
  }
4
ответ дан 3 December 2019 в 00:53
поделиться

Полагайте также, что Unix и Windows имеют созданный в стопке каталога: pushd и popd. Это чрезвычайно просто в использовании.

1
ответ дан 3 December 2019 в 00:53
поделиться

Вообще выполнимо пытаться использовать полностью определенные количественно пути и не сделать какие-либо предположения, на котором каталоге Вы в настоящее время находитесь в? например.

use FileHandle;
use FindBin qw($Bin);
# ...
my $file = new FileHandle("< $Bin/somefile");

вместо

use FileHandle;
# ...
my $file = new FileHandle("< somefile");

Это, вероятно, будет легче в конечном счете, поскольку Вы не должны волноваться о странных вещах, происходящих (Ваша смерть сценария или быть уничтоженным, прежде чем она могла отложить текущий рабочий каталог туда, где это было), и является вполне возможно более портативным.

0
ответ дан 3 December 2019 в 00:53
поделиться