Wie führe ich einen Befehl mit einem Verzeichnis als Argument aus und cd dann auf dasselbe? Ich bekomme "keine solche Datei oder Verzeichnis"

15

Ich möchte eine kurze Funktion erstellen, um Folgendes zu tun. Angenommen, ich verschiebe die Datei 'file.tex' in mein Dokumentenverzeichnis:

mv file.tex ~/Documents

Dann möchte ich cdzu diesem Verzeichnis:

cd ~/Documents

Ich möchte dies auf ein beliebiges Verzeichnis verallgemeinern, damit ich dies tun kann:

mv file.tex ~/Documents
follow

und lassen Sie den followBefehl das Ziel aus dem vorherigen Befehl lesen und dann entsprechend ausführen. Bei einem einfachen Verzeichnis spart dies nicht viel Zeit, aber wenn Sie mit verschachtelten Verzeichnissen arbeiten, wäre es enorm, wenn Sie nur diese verwenden könnten

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

Ich dachte, es wäre relativ einfach und ich könnte so etwas tun:

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

aber das scheint nicht zu funktionieren. Wenn ich wiederhole $place, erhalte ich die gewünschte Zeichenfolge (ich teste sie mit ~/Documents), aber der letzte Befehl wird zurückgegeben

No such file or directory

Das Verzeichnis existiert auf jeden Fall. Ich bin ratlos. Könntest du mir helfen?

Feuer
quelle
Ich möchte darauf hinweisen, dass Symlinks eine sehr gute Alternative sind , wenn es Ihnen nichts ausmacht, file.texden ursprünglichen Speicherort beizubehalten , da Sie nur einmal verlinken müssen und dann immer auf die neueste Version verweisen.
Kroltan
5
Einfacher: Geben Sie cd alt + ein, .um das letzte Token des vorherigen Befehls zu ersetzen. Wiederholen Sie diesen Vorgang, um weiter in die Geschichte der letzten Token zurückzugehen. (Ich sage Token nicht Arg, weil foo &Grabs &das letzte Token ist.) Sie können ein numerisches Argument verwenden (zum Beispiel mit Escape-3 Alt +.).
Peter Cordes
Siehe auch mkdir cd combo
Christopher Bottoms

Antworten:

18

Anstatt eine Funktion zu definieren, können Sie die Variable verwenden $_, die bis zum letzten Argument des vorherigen Befehls von erweitert wird bash. Also benutze:

cd "$_"

nach mvbefehl.

Sie können auch die Verlaufserweiterung verwenden:

cd !:$

Wenn Sie eine Funktion verwenden müssen:

follow () { cd "$_" ;}

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

NB: Diese Antwort ist auf das genaue Format der Befehlszeilenargumente ausgerichtet, das Sie beim Umgang mit Positionsparametern verwendet haben. Für andere Formate, z. B. mv -t foo bar.txtmüssen Sie vorher bestimmte Überprüfungen vornehmen, ein Wrapper wäre dann angebracht.

heemayl
quelle
Ihre Verlaufserweiterung (cd!: $) Funktioniert einwandfrei. Vielen Dank. Die andere (cd "$ _") enthält jedoch nicht: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: Keine solche Datei oder kein solches Verzeichnis Danke.
Feuer
Ich habe immer (etwas verschwenderisch) entweder cd !$oder getippt cd $(dirname !$). Wusste nichts über die $_Variable!
Kalvin Lee
Nun , was passiert , wenn ich mv -t ~/Documents file.texstatt mv file.tex ~/Documents? Fazit: Ich bin mir nicht sicher, ob dies im Allgemeinen lösbar ist ... eine Wrapper-Funktion, oder ob Neuimplementierungen mvbesser sind ...
ein CVn
@ MichaelKjörling Wird nicht einfach funktionieren..dieses Beispiel soll nur den Fall abdecken, den OP hat, nicht die
Randfälle
Du brauchst den Doppelpunkt nicht; !$ist gleichbedeutend mit !:$und schneller zu tippen.
Wildcard
14

Bei Standard-Bash-Tastenkombinationen Alt.kopiert die Kombination das letzte Argument der vorherigen Befehlszeile in das aktuelle. Also tippen

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

ergäbe

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

und wäre noch weniger tippend als das Wort follow.

Wenn Sie diese Alt.Kombination wiederholen, werden die letzten Argumente aller vorherigen Befehlszeilen durchsucht.

Anhang: Der Name des Bash-Befehls, der dieser Tastenkombination entspricht, ist yank-last-argoder insert-last-argument. Sie finden es in der bash-Manpage unter "Befehle zum Manipulieren des Verlaufs" oder im ausführlicheren Bash-Referenzhandbuch .)

Dubu
quelle
1
Das ist schlau. Vielen Dank! Ich hatte keine Ahnung, dass es das gibt.
Feuer
@Fire Ich habe Referenzen für diese Befehle hinzugefügt, damit Sie viel interessantere Tastenzuordnungen finden können (und sie sofort wieder vergessen, wie ich es immer tue).
Dubu
1
Sie können auch verwenden , <esc>dann .das gleiche Ergebnis wie zu bekommen <alt>+., das nützlich , wenn Sie remapped capslock haben zu entkommen :)
gnur
1
@ Gnur vi (m) Benutzer, nehme ich an. ;-)
Dubu
6

Mit ziemlicher Sicherheit stoßen Sie auf das Problem, dass die Tilde-Erweiterung vor der Parameter-Erweiterung stattfindet, was durch ein kurzes Beispiel erklärt werden kann:

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

Dies kann mit angesprochen werden eval. Wie auch immer, Sie werden es brauchen eval, weil Sie Befehle aus dem Verlauf abrufen und sie beliebige Erweiterungen enthalten können, wie zum Beispiel:

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

(Es gibt Probleme, zum Beispiel, dass die erneute Erweiterung dieser Werte möglicherweise nicht mehr mit der ursprünglichen Erweiterung übereinstimmt. Angenommen, es compute_folder_namehandelt sich um eine Funktion, die eine globale Variable inkrementiert.)

Kaz
quelle
4
Das brauchst du nicht eval. (Überhaupt.) Aber gute Beobachtung der Erweiterungssequenzprobleme. Wenn Sie die größere Zweckmäßigkeit der Geschichtserweiterung evalhier erwähnen , ist dies meiner Meinung nach die beste Antwort. Keiner der anderen erklärt tatsächlich, warum die Lösung des Original-Posters nicht funktionierte.
Wildcard