Come eseguire un comando con una directory come argomento, quindi cd sullo stesso? Ottengo "nessun file o directory"


15

Vorrei costruire una breve funzione per fare quanto segue. Diciamo che sposto il file 'file.tex' nella mia directory dei documenti:

mv file.tex ~/Documents

Quindi, vorrei cdquella directory:

cd ~/Documents

Vorrei generalizzare questo in qualsiasi directory, in modo da poterlo fare:

mv file.tex ~/Documents
follow

e chiedi al followcomando di leggere la destinazione dal comando precedente, quindi esegui di conseguenza. Per una directory semplice, questo non fa risparmiare molto tempo, ma quando si lavora con directory nidificate, sarebbe straordinario poter usare

mv file.tex ~/Documents/folder1/subfolder1
follow

Ho pensato che sarebbe stato relativamente semplice e che avrei potuto fare qualcosa del genere:

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

ma questo non sembra funzionare. Se echo $place, ottengo la stringa desiderata (la sto provando con ~/Documents), ma restituisce l'ultimo comando

No such file or directory

La directory esiste sicuramente. Sono in perdita. Puoi aiutarmi?


Vorrei sottolineare che se non ti dispiace mantenere file.texla posizione originale, i collegamenti simbolici sono un'ottima alternativa, poiché devi collegarti solo una volta, quindi rimanderà sempre all'ultima versione.
Kroltan,

5
Modo più semplice: digita cd alt + .per sostituire l'ultimo token del comando precedente. Ripeti per tornare indietro nella storia dei token finali. (Dico token non arg, perché foo &afferra &come token finale.) Puoi usare un argomento numerico (con escape-3 alt +. Per esempio).
Peter Cordes,


Risposte:


18

Invece di definire una funzione, è possibile utilizzare la variabile $_, che viene espansa all'ultimo argomento del comando precedente da bash. Quindi usa:

cd "$_"

dopo il mvcomando.

Puoi anche usare l'espansione della cronologia:

cd !:$

Se è necessario utilizzare una funzione:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

NB: Questa risposta è indirizzata al formato esatto degli argomenti della riga di comando che hai usato mentre stiamo trattando i parametri posizionali. Per altri formati mv -t foo bar.txt, ad esempio , è necessario incorporare preventivamente controlli specifici, quindi un wrapper sarebbe appropriato.


L'espansione della cronologia (cd!: $) Funziona perfettamente. Grazie. Tuttavia, l'altro (cd "$ _") non: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: nessun file o directory di questo tipo accetterò volentieri la tua risposta come completamente corretta, e grazie.
Fuoco

Ho sempre digitato (un po 'inutilmente) o cd !$o cd $(dirname !$). Non sapevo della $_variabile!
Kalvin Lee,

Ora cosa succede se lo faccio mv -t ~/Documents file.texinvece di mv file.tex ~/Documents? In conclusione, non sono sicuro che questo sia risolvibile nel caso generale ... una funzione wrapper in giro o che i reimplementamenti mvpotrebbero essere migliori ...
un CVn

@ MichaelKjörling Non funzionerà semplicemente..questo esempio è solo per coprire il caso che OP ha, non i casi limite (o tutti) ..
heemayl

Non hai bisogno dei due punti; !$è equivalente !:$e più veloce da digitare.
Carattere jolly

14

Con i tasti bash standard, la combinazione Alt.copierà l'ultimo argomento della precedente riga di comando in quello corrente. Quindi, digitando

$ mv foo ~/some/long/path/
$ cd <Alt><.>

cederebbe

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

e scriverebbe anche meno della parola follow.

Per maggiore comodità, la ripetizione della Alt.combinazione sfoglia gli ultimi argomenti di tutte le precedenti righe di comando.

Addendum: il nome del comando bash corrispondente a questa combinazione di tasti è yank-last-argo insert-last-argument. Può essere trovato nella manpage di bash sotto "Comandi per manipolare la storia" o nel più esaustivo Manuale di riferimento di Bash .)


1
È intelligente. Grazie! Non avevo idea che esistesse.
Fuoco

@Fire Ho aggiunto riferimenti per quei comandi, così puoi trovare combinazioni di tasti molto più interessanti (e immediatamente dimenticarle di nuovo, come faccio sempre).
Dubu,

1
Puoi anche usare <esc>quindi .per ottenere lo stesso risultato <alt>+., utile quando hai rimappato il maiuscolo per scappare :)
gnur

1
@gnur vi (m) utente, suppongo. ;-)
Dubu

6

Stai quasi sicuramente incontrando il problema che l'espansione della tilde ha luogo prima dell'espansione dei parametri, che può essere spiegata da un esempio sintetico:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

Questo può essere affrontato con eval. In ogni caso, ne avrai bisogno eval, perché stai estraendo comandi dalla cronologia e possono contenere espansioni arbitrarie, come:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(Ci sono problemi, come il fatto che la riespansione di questi valori potrebbe non corrispondere più all'espansione originale verificatasi. Supponiamo che compute_folder_namesia una funzione che incrementa alcune variabili globali.)


4
Non hai bisogno eval. (Mai.) Ma è bene individuare i problemi della sequenza di espansione. Se menzionate la maggiore consigliabile dell'espansione della storia nell'usare evalqui, questa sarà la migliore risposta secondo me; nessuno degli altri in realtà spiega perché la soluzione del Poster originale non sia riuscita a funzionare.
Carattere jolly
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.