Cambia la directory corrente da uno script Bash


190

È possibile cambiare la directory corrente da uno script?

Voglio creare un'utilità per la navigazione delle directory in Bash. Ho creato uno script di test simile al seguente:

#!/bin/bash
cd /home/artemb

Quando eseguo lo script dalla shell Bash la directory corrente non cambia. È possibile cambiare la directory shell corrente da uno script?


2
Solo un suggerimento di miglioramento: se si utilizza pushd(eventualmente reindirizzato a >/dev/nullper sopprimerne l'output) anziché cd, è possibile in seguito tornare alla directory precedente con popd.
mklement0

Risposte:


173

Devi convertire il tuo script in una funzione shell:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

Il motivo è che ogni processo ha la sua directory corrente e quando si esegue un programma dalla shell viene eseguito in un nuovo processo. Lo standard "cd", "pushd" e "popd" sono integrati nell'interprete della shell in modo da influenzare il processo della shell.

Rendendo il programma una funzione di shell, si sta aggiungendo il proprio comando in-process e quindi qualsiasi cambiamento di directory viene riflesso nel processo di shell.


2
come lo faresti in tcsh?
joedborg,

4
+1. Una cosa che ho notato era nel file, dobbiamo definire la funzione prima di chiamarla. Potrebbe aiutare qualcuno inesperto come me.
Bhushan,

Qual è la grande differenza tra la definizione di una funzione e la creazione di un alias?
Ciao Arrivederci,

1
Dopo aver creato questo file myprog.sh e averlo aggiunto al file .bashrc, come posso eseguire lo script? Devo chiamare la mia funzione da un altro file shell o direttamente dalla shell? Sembra che non funzioni in nessun modo ...
Andrea Silvestri,

1
@AndreaSilvestri Disconnettersi e riconnettersi o origine .bashrc. L'aggiunta a .bashrc non fa nulla fino a quando non viene eseguito .bashrc.
Jon Strayer,

214

Quando si avvia lo script, viene creato un nuovo processo che eredita solo l'ambiente. Quando finisce, finisce. Il tuo ambiente attuale rimane così com'è.

Invece, puoi iniziare il tuo script in questo modo:

. myscript.sh

Il .valuterà lo script nel contesto attuale, quindi potrebbe essere alterato


4
+1 perché hai ragione. Anche se dubito sinceramente che vorrà procurarsi uno script per cambiare directory ogni volta che ne ha bisogno. Inoltre, le .shestensioni sono totalmente eww. Non usarli.
lhunath,

1
Sì, di solito è meglio non usarlo in questo modo. Il più delle volte sei contento che il tuo ambiente attuale non soffra. Ma poi ho degli script per fare alcune attività di installazione per me incluso il passaggio al posto giusto e poi io. anche loro. Btw. .sh è ovviamente una questione di stile personale. Probabilmente non lo userei durante l'installazione di script a livello di sistema. Ma nel mio ~ / bin li uso per sapere cosa è cosa :)
Norbert Hartl,

11
@lhunath Perché le estensioni .sh sono totalmente eww?
Carl Pritchett,


1
Per me il ragionamento in quell'articolo è falso. Sembra che il risultato sia stato conosciuto in anticipo, ma trovarne le ragioni non è stato così facile. Quindi sostengo che è una questione di stile personale, nient'altro.
Norbert Hartl,

55

Alla luce della illeggibilità e della complicanza eccessiva delle risposte, credo che questo sia ciò che il richiedente dovrebbe fare

  1. aggiungi quello script a PATH
  2. eseguire lo script come . scriptname

Il .(punto) farà in modo che lo script non sia eseguito in una shell figlio.


38

Mettendo insieme quanto sopra, puoi creare un alias

alias your_cmd=". your_cmd"

se non vuoi scrivere il primo "." ogni volta che si desidera eseguire il source dello script nell'ambiente shell o se semplicemente non si desidera ricordare che è necessario che lo script funzioni correttamente.


Questo rimarrà persistente durante i riavvii?
SDsolar,

1
@SDsolar Devi aggiungerlo al tuo file ~ / .bashrc per renderlo persistente. Funziona come un incanto per me.
Rafał G.,

Può essere inserito in ~ / .bash_aliases
Champ

@Champ ~/.bash_aliasesnon viene sempre fornito all'avvio di Bash.
Mateusz Piotrowski l'

31

Se stai usando bash puoi provare alias:

nel file .bashrc aggiungi questa riga:

alias p='cd /home/serdar/my_new_folder/path/'

quando scrivi "p" sulla riga di comando, cambierà la directory.


1
+1 per alias. la funzione shell è interessante ma l'OP ha richiesto un semplice nav con cd. Immagino che molte persone abbiano bisogno di uno script come questo per navigare tra i rami del codice sorgente e per questo alias è sufficiente
Brad Dre,

19

Se esegui uno script bash, funzionerà sul suo ambiente attuale o su quelli dei suoi figli, mai sul genitore.

Se l'obiettivo è eseguire il tuo comando: goto.sh / home / test Quindi lavorare in modo interattivo in / home / test in un modo è quello di eseguire una shell secondaria interattiva bash all'interno del tuo script:

#!/bin/bash
cd $1
exec bash

In questo modo sarai in / home / test fino all'uscita (exit o Ctrl + C) di questa shell.


Ho pensato che questo avrebbe risolto il problema per uno script di shell che stavo eseguendo, ma invece avvia la shell e dimentica ciò che volevo.
vwvan,

14

Con pushd la directory corrente viene inserita nello stack di directory e viene cambiata nella directory specificata, popd ottiene la directory in cima allo stack e passa quindi ad essa.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null

2
Questo risponde alla mia domanda: distribuire attivamente questa soluzione con uno script S3 init e funziona perfettamente. Grazie @seb.
19h,

5

Vai semplicemente a

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

e aggiungi questo codice accanto all'ultima riga:

alias yourcommand="cd /the_path_you_wish"

Quindi chiudere l'editor.

Quindi digitare:

source ~/.bashrc or source ~/.bash_profile on MAC.

ora puoi usare: il tuo comando nel terminale



3

Fondamentalmente usiamo cd..tornare da ogni directory. Ho pensato di renderlo più semplice fornendo il numero di directory con cui è necessario tornare alla volta. Puoi implementarlo usando un file di script separato usando il comando alias. Per esempio:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

Dopo aver usato source code.shnella shell corrente puoi usare:

$back 2 

per tornare indietro di due passi dalla directory corrente. Spiegato in dettaglio qui . Viene anche spiegato laggiù come inserire il codice in ~ / .bashrc in modo che ogni nuova shell aperta abbia automaticamente questo nuovo comando alias. È possibile aggiungere un nuovo comando per accedere a directory specifiche modificando il codice aggiungendo altri if conditionse diversi argomenti. Puoi anche estrarre il codice da git qui .


Bella soluzione, quindi non rovinare mai il tuo profilo bash :)
J4cK

0

Questo approccio è più facile per me.

Supponiamo su un iMac personale di cui sei un amministratore, nella directory predefinita quando viene aperta una finestra di comando, / Users / jdoe, questa sarà la directory da cui accedere a: /Users/jdoe/Desktop/Mongo/db.3.2.1 /bidone.

Questi sono i passaggi che possono svolgere il lavoro:

  1. vi mongobin, in cui sono entrato: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bincome prima riga.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Ecco!


0

Ho anche creato un'utilità chiamata capra che puoi usare per facilitare la navigazione.

È possibile visualizzare il codice sorgente su GitHub .

A partire dalla v2.3.1 la panoramica sull'uso è simile alla seguente:

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix

0

Mi piace fare la stessa cosa per progetti diversi senza avviare una nuova shell.

Nel tuo caso:

cd /home/artemb

Salva the_script come:

echo cd /home/artemb

Quindi accendilo con:

\`./the_script\`

Quindi si arriva alla directory usando la stessa shell.



0

Dichiara il tuo percorso:

PATH='/home/artemb'     
cd ${PATH}

0

Basta scrivere PWDed esportarlo all'interno dello script e la modifica continuerà.

export PWD=/your/desired/directory
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.