Qual è la migliore pratica per cambiare directory di lavoro all'interno degli script?

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

  •  04-07-2019
  •  | 
  •  

Domanda

Pensi che cambiare le directory all'interno degli script bash o Perl sia accettabile? O si dovrebbe evitare di farlo a tutti i costi?

Qual è la migliore pratica per questo problema?

È stato utile?

Soluzione

La directory di lavoro corrente è locale nella shell in esecuzione, quindi non puoi influenzare l'utente a meno che non stia "punteggiando". (eseguendolo nella shell corrente, anziché eseguirlo normalmente creando un nuovo processo di shell) il tuo script.

Un ottimo modo per farlo è usare i subshells, cosa che faccio spesso negli alias.

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

La paratesi farà in modo che il comando venga eseguito da una sotto-shell, e quindi non influenzerà la directory di lavoro della mia shell. Inoltre non influirà sull'ultima directory di lavoro, quindi cd -; funziona come previsto.

Altri suggerimenti

Come ha detto Hugo, non è possibile influenzare il CWD del processo genitore, quindi non ci sono problemi.

Dove la domanda è più applicabile è se non controlli l'intero processo, come in una subroutine o in un modulo. In quei casi si desidera uscire dalla subroutine nella stessa directory inserita, altrimenti si insinua una sottile azione a distanza che causa bug.

Puoi farlo a mano ...

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

    ...do some work...

    chdir $orig_cwd;
}

ma questo ha dei problemi. Se la subroutine ritorna presto o muore (e l'eccezione è intrappolata) il tuo codice sarà ancora in some / dir . Inoltre, i chdir potrebbero fallire e devi ricordarti di controllare ogni utilizzo. Bleh.

Fortunatamente, ci sono un paio di moduli per renderlo più semplice. Il file :: pushd è uno, ma preferisco File :: chdir .

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

    ...do some work...
}

File :: chdir trasforma le directory cambiando nell'assegnazione a $ CWD . E puoi localizzare $ CWD in modo che si resetti alla fine del tuo ambito, qualunque cosa accada. Controlla inoltre automaticamente se chdir ha esito positivo e genera un'eccezione in caso contrario. A volte lo usa negli script perché è così conveniente.

Non lo faccio spesso, ma a volte può risparmiare un bel po 'di mal di testa. Assicurati solo che se cambi directory, torni sempre alla directory da cui sei partito. Altrimenti, la modifica dei percorsi del codice potrebbe lasciare l'applicazione da qualche parte non dovrebbe essere.

Per Perl, hai il modulo File :: pushd di CPAN che rende abbastanza elegante la modifica locale della directory di lavoro. Citando la sinossi:

  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
  }

Seguirò i commenti di Schwern e Hugo sopra. Nota l'attenzione di Schwern sul ritorno alla directory originale in caso di uscita imprevista. Ha fornito il codice Perl appropriato per gestirlo. Indico il comando trap della shell (Bash, Korn, Bourne).

trap " cd $ saved_dir " 0

tornerà a saved_dir all'uscita di subshell (se stai. 'in corso il file).

mike

Considera anche che Unix e Windows hanno uno stack di directory incorporato: pushd e popd . È estremamente facile da usare.

È assolutamente possibile provare a utilizzare percorsi completamente quantificati e non fare ipotesi su quale directory ci si trovi attualmente? per es.

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

anziché

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

Questo probabilmente sarà più facile a lungo termine, poiché non devi preoccuparti di cose strane che accadono (il tuo script muore o viene ucciso prima che possa riportare l'attuale directory di lavoro dove era), ed è piuttosto forse più portatile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top