Ist es möglich, einen Teil eines Befehls zu benennen, um ihn später im selben Befehl wiederzuverwenden?

7

Wenn ich eine aufgerufene Datei longfilevon /longpath/nach verschieben möchte, /longpath/morepath/kann ich so etwas tun

mv (/longpath)/(longfile) $1/morepath/$2

dh kann ich die Bash wissen lassen, dass sie sich an einen bestimmten Teil der Eingabe erinnern soll, damit ich sie später in derselben Eingabe wiederverwenden kann? (Im obigen Beispiel verwende ich einen imaginären Erinnerungsbefehl, der in Klammern eingeschlossen ist, und einen imaginären Wiederverwendungsbefehl $, der den Inhalt der Gruppen einfügt.)

Bananach
quelle
2
Warum dann nicht eine Variable?
Heemayl
Zum Beispiel passt das Obige in eine Zeile und hinterlässt keine zwei Variablen, die nie wieder verwendet werden. Ich bin nicht sicher, ob es mehr Vorteile / Anwendungen gibt, ich war meistens neugierig
Bananach

Antworten:

22

Sie könnten dies tun:

mv /longpath/longfile !#:1:h/morepath/

Siehe https://www.gnu.org/software/bash/manual/bashref.html#History-Interaction

  • !# ist der aktuelle Befehl
  • :1 ist das erste Argument in diesem Befehl
  • :h ist der "Kopf" - denken dirname
  • /morepath/ hängt das an den Kopf
  • und Sie verschieben eine Datei in ein Verzeichnis, sodass der Basisname beibehalten wird.

Wenn Sie den Namen "longfile" ändern möchten, fügen Sie beispielsweise die Erweiterung ".txt" hinzu

mv /longpath/longfile !#:1:h/morepath/!#:1:t.txt

Persönlich würde ich mit meiner Maus ausschneiden und einfügen. In der Praxis werde ich nie viel komplizierter als !!oder !$oder!!:gs/foo/bar/

Glenn Jackman
quelle
14

Sie können dies auch mit der Erweiterung der Zahnspange tun:

mv /longpath/{,morepath/}longfile

Die Shell erweitert dies so, dass der mvBefehl es genauso sieht wie:

mv /longpath/longfile /longpath/morepath/longfile
Platzhalter
quelle
9

Wenn Sie die Befehlszeile effizienter eingeben möchten , sind möglicherweise verschiedene Verknüpfungen für die Leseleitung hilfreich. Readline ist bereits in Ihre Shell integriert. Für Ihren speziellen Fall könnten Sie Teile Ihrer Linie ziehen / löschen und sie dann vom Readline-Killiring zurückrufen.

Wenn Sie die Umgebungsvariable EDITOR auf Ihren bevorzugten Editor eingestellt haben, kopiert Strg-X, Strg-E Ihre aktuelle Befehlszeile in das Editorfenster, in dem Sie die gesamte Editorleistung zum Ändern Ihrer Zeile haben können. Sobald Sie fertig sind, speichern Sie den Editor und beenden ihn. Die Zeile wird in Ihrer Shell ausgeführt.

Tagwint
quelle
Nachdem ich wochenlang Vim gelernt hatte, war ich tatsächlich verärgert, dass ich den Pfeil nach links immer noch in der Konsole halten musste, um mich in meinen Befehlen zu bewegen. Jetzt kann ich all meine neu erworbene Vim-Magie dafür anwenden. Wunderbar!
Bananach
2
@ Bananach: Sie können bash auch auf vi-mode setzen: set -o viin bashrc. Durch Drücken von esc in der Befehlszeile gelangen Sie in den normalen Modus von vim.
Nick Matteo
1
@kundor, ich benutze set -o vimich selbst, aber es ist bei weitem nicht so leistungsfähig wie der normale Modus von Vim - es enthält eine Teilmenge der Befehle von POSIX vi. Trotzdem sehr nützlich und Sie können <Esc>vden Befehl zum Bearbeiten in Vim öffnen.
Wildcard
4

Für so etwas wie den speziellen Fall, nach dem Sie fragen, können Sie auch eine Unterschale verwenden.

mv (/longpath)/(longfile) $1/morepath/$2

wird

( cd /longpath; mv longfile morepath/ )

während Sie Ihr aktuelles Arbeitsverzeichnis in der Shell behalten, in der Sie arbeiten.

Dies ist nicht ganz unähnlich zu Wildcards Vorschlag, eine Shell-Erweiterung zu verwenden , kann jedoch für komplexere Situationen durchgeführt werden, als ein einfaches Etwas, das nur in einem Argument enthalten ist, ohne weiteres unterstützen kann.

ein CVn
quelle
Es ist erwähnenswert, dass die Leerzeichen um die Klammern der Lesbarkeit dienen. sie sind nicht erforderlich (geschweifte Klammern für Befehl Gruppierung , wo Leerzeichen Trennung im Gegensatz zu verwenden ist erforderlich).
Wildcard