¿Cuál es la mejor práctica para cambiar directorios de trabajo dentro de scripts?

StackOverflow https://stackoverflow.com/questions/240661

  •  04-07-2019
  •  | 
  •  

Pregunta

¿Crees que es aceptable cambiar directorios dentro de scripts de bash o Perl? ¿O debería uno evitar hacer esto a toda costa?

¿Cuál es la mejor práctica para este problema?

¿Fue útil?

Solución

El directorio de trabajo actual es local al shell de ejecución, por lo que no puede afectar al usuario a menos que esté " punteado " (ejecutándolo en el shell actual, en lugar de ejecutarlo normalmente creando un nuevo proceso de shell) su script.

Una muy buena manera de hacer esto es usar subshells, que a menudo hago en los alias.

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

El paranthesis se asegurará de que el comando se ejecute desde un sub-shell, y por lo tanto no afectará el directorio de trabajo de mi shell. Además, no afectará el último directorio de trabajo, por lo que cd -; funciona como se esperaba.

Otros consejos

Como dijo Hugo, no puedes efectuar el cwd de tu proceso padre, por lo que no hay problema.

Donde la pregunta es más aplicable es si no controla todo el proceso, como en una subrutina o módulo. En esos casos, querrá salir de la subrutina en el mismo directorio en el que ingresó, de lo contrario se arrastran sutiles acciones a distancia en las que se producen errores.

Puedes hacerlo a mano ...

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

    ...do some work...

    chdir $orig_cwd;
}

pero eso tiene problemas. Si la subrutina regresa antes de tiempo o muere (y la excepción está atrapada), su código aún estará en some / dir . Además, los chdir s pueden fallar y usted debe recordar verificar cada uso. Bleh.

Afortunadamente, hay un par de módulos para hacer esto más fácil. File :: pushd es uno, pero prefiero File :: chdir .

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

    ...do some work...
}

File :: chdir convierte los directorios en asignados a $ CWD . Y puede localizar $ CWD para que se reinicie al final de su alcance, sin importar qué. También verifica automáticamente si el chdir tiene éxito y, de lo contrario, lanza una excepción. A veces lo usa en scripts porque es muy conveniente.

No hago esto a menudo, pero a veces puede ahorrar un poco de dolor de cabeza. Solo asegúrese de que si cambia los directorios, siempre vuelva a cambiar al directorio desde el que comenzó. De lo contrario, cambiar las rutas de código podría dejar la aplicación en un lugar donde no debería estar.

Para Perl, tiene el módulo File :: pushd de CPAN, que hace que cambiar localmente el directorio de trabajo sea bastante elegante. Citando la sinopsis:

  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
  }

Voy a secundar los comentarios de Schwern y Hugo arriba. Tenga en cuenta la precaución de Schwern acerca de regresar al directorio original en caso de una salida inesperada. Él proporcionó el código apropiado de Perl para manejar eso. Señalaré el comando de captura (Bash, Korn, Bourne).

captura " cd $ saved_dir " 0

volverá a saved_dir en la salida de subshell (si está .'ing el archivo).

mike

Considera también que Unix y Windows tienen una pila de directorios integrada: pushd and popd . Es extremadamente fácil de usar.

¿Es posible probar y usar rutas completamente cuantificadas y no hacer suposiciones en qué directorio se encuentra actualmente? por ejemplo

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

en lugar de

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

Esto probablemente será más fácil a largo plazo, ya que no tiene que preocuparse por que sucedan cosas extrañas (su secuencia de comandos se muere o se elimina antes de que el directorio actual de trabajo pueda volver a donde estaba), y es bastante posiblemente más portátil.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top