è possibile cambiare la directory di lavoro della shell genitore a livello di codice?


8

Voglio scrivere un po 'di codice per permettermi di passare ad alcune directory che di solito vado. Di 'che questo programma è mycded /a/very/long/path/nameè la directory in cui voglio andare.

Quindi posso semplicemente digitare mycd 2invece di cd /a/very/long/path/name. Qui presumo mycdsappia si 2riferisce a questo /a/very/long/path/name. Ci potrebbe essere anche mycd 1, mycd 3, ecc ...

Il problema è che devo scrivere mycdcome uno script di shell e digitare . mycd 2per fare la cosa desiderata perché altrimenti lo script viene semplicemente eseguito in uno script figlio che non cambia nulla della shell genitrice a cui tengo davvero.

La mia domanda è:

  • posso farlo senza usare source? perché . mycdpresuppone che mycddebba essere uno script di shell e questo potrebbe anche introdurre alcune funzioni che non voglio.

  • posso implementarlo in altri linguaggi di programmazione?

Risposte:


23

crea mycduna funzione in modo che il cdcomando venga eseguito nella tua shell corrente. Salvalo nel tuo file ~ / .bashrc.

function mycd {
    if (( $# == 0 )); then
        echo "usage: $FUNCNAME [1|2|3|...]"
        return
    fi
    case $1 in
        1) cd /tmp ;;
        2) cd /a/very/long/path/name ;;
        3) cd /some/where/else ;;
        *) echo "unknown parameter" ;;
    esac
}

Grazie, non ho pensato di usare le funzioni e questo abilita tutto: posso ora mycdpassare $@a qualsiasi programma che mi piace.
Javran,

Assicurati di citare in "$@"modo che tutti gli argomenti contenenti spazi siano gestiti correttamente.
Glenn Jackman,

9

Non è possibile modificare la directory corrente di una shell da un altro processo. Solo il processo stesso può modificare la propria directory corrente. Ciò vale anche per alcune altre caratteristiche come variabili di ambiente e descrittori di file.

In realtà è possibile influenzare la directory corrente di un altro processo facendogli eseguire una chdirchiamata di sistema tramite la ptracechiamata di sistema, che è ciò che consente ai debugger di funzionare. Tuttavia, se il processo mantiene alcune strutture di dati interne che devono essere coerenti con l'attuale directory corrente, è probabile che il programma si blocchi. Per una shell, questo approccio non ha possibilità di funzionare.

È necessario disporre che il codice venga eseguito dalla shell stessa. Il modo normale di procedere sarebbe renderlo una funzione shell e memorizzarlo nel tuo ~/.bashrc. Se ciò non è possibile, ad esempio perché è il codice che si desidera distribuire, scrivere un file sorgente della shell che contiene la definizione della funzione e dire alle persone che la loro shell interattiva legga il file con il .comando .


1
Esiste effettivamente la possibilità di farlo "funzionare", ma non è banale, soggetto a errori e dovrebbe essere evitato a tutti i costi. Per dimostrare che in realtà è "possibile", considerare questo script di shell in cui il genitore è Bash: ws=$1; gdb -p $(ps h -o ppid -p $$) -ex "call chdir(\"$wd\")" -ex "call set_working_directory(\"$wd\")" -ex detach -ex q -batch. Eseguire come braindead-cd-parent /. Vedrai che pwdritorna /e così si comportano ls, ecc. Ma il prompt ( PS1) è ancora invariato, gli occhi delle persone sono feriti, ecc. Quindi non farlo anche se è possibile.
Lekensteyn,

1
@Lekensteyn Questo è il ptracemetodo che menziono. Funziona bene su programmi a cui non importa molto della loro directory corrente. In una shell, molte cose ( PWDvariabili, prompt, ecc.) Si sbaglieranno e la shell potrebbe bloccarsi o comportarsi diversamente.
Gilles 'SO- smetti di essere malvagio' il

5

Come hai sottolineato te stesso, gli script di shell sono sempre eseguiti in una sottoshell, che non può influenzare la sua shell madre.

Puoi comunque ...

  • usa un alias:
    alias mycd2='cd /a/very/long/path/name'
  • fai in modo che il tuo script 1 emetta un comando shell valido ...

    #!/bin/bash
    if [ "x$1" = "x2" ]
    then
        echo "cd /a/very/long/path/name"
    fi

    ... ed esegui il suo output: $(mycd 2)

1: Probabilmente vorrai usare caseun'istruzione piuttosto che la ifcondizione nell'esempio.


5
Un alias è passabile. Una sceneggiatura è lo stesso problema che ha già. Questa domanda urla la funzione shell.
Ricky Beam,
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.