Linux MV-Datei mit langem Namen

19

Unter Linux benenne ich manchmal Dateien wie folgt um:

mv dir1/dir2/dir3/file.txt  dir1/dir2/dir3/file.txt.old

Beachten Sie, dass ich die Datei nur umbenennen und nicht in ein anderes Verzeichnis verschieben möchte.

Gibt es einen Befehl, mit dem ich eine Kurzversion dieses Befehls ausführen kann? Ich denke etwas wie:

mv dir1/dir2/dir3/file.txt  file.txt.old

oder vielleicht sogar so etwas wie (einfach an den Namen anhängen):

mv dir1/dir2/dir3/file.txt  {}.old

Mein Ziel ist es, nicht noch einmal den vollständigen Pfad angeben zu müssen.

Ich weiß, dass diese "Beispiele", die ich geschrieben habe, nicht funktionieren, aber es ist nur eine Idee von dem, was ich erreichen möchte.

Ich möchte nicht in das Verzeichnis hineingehen müssen.

Santiago Arizti
quelle
8
Warum wechseln Sie nicht in das Verzeichnis? Es ist schnell und löst Ihr Problem.
Michael Hampton
Ich habe es mit vielen Unterverzeichnissen von demselben Ort zu tun. Es ist langsamer, wenn ich jedes Mal zu diesem übergeordneten
Verzeichnis zurückkehren muss
3
Niemand sagte, Sie müssten in ein anderes Verzeichnis wechseln, nur das, das Sie möchten.
Michael Hampton
Beachten Sie, dass dies (cd dir1/dir2/dir3 && exec mv file.txt{,.old})effektiv die gleiche Leistung wie der Code ohne den Unterprozess hat, da dies während des externen Befehlsaufrufs execvermieden wird fork(), sodass Sie genau eine Verzweigung in beide Richtungen haben.
Charles Duffy

Antworten:

45

für eine einzelne Datei versuchen

mv dir1/dir2/dir3/file.{txt,txt.old}

Wohin das X{a,b}Konstrukt erweitert wird, Xa Xbkönnen Sie mit eine Vorschau anzeigen

echo dir1/dir2/dir3/file.{txt,txt.old}

um zu sehen, ob es Ihren Bedürfnissen entspricht.

Hinweis:

  1. das für mehrere Dateien

    mv dir1/dir2/dir3/file{1,2,3}.{txt,txt.old}
    

Es ist unwahrscheinlich, dass Sie das erreichen, was Sie wollen. (Dies wird zu einer Mischung aus file.txt file1.txt.old file2.txt erweitert ...)

  1. {txt,txt.old}kann laut {,.old}Kommentar gekürzt werden

  2. Wenn der Verzeichnisname eindeutig ist, kann ein Platzhalter verwendet werden.

    mv *1/*2/d*/*.{,old}
    

für die Verwendung mehrerer Dateien rename

rename -n s/txt/old.txt/ dir1/dir2/dir3/file*.txt 

Drop -nwirksam Umbenennungs haben.

Archemar
quelle
1
schön, ich wusste nicht, wie ich mich ausdehnen soll! Vielen Dank
Santiago Arizti
14
Würde das mv dir1/dir2/dir3/file.txt{,.old}nicht auch funktionieren und noch kürzer sein?
Josh
3
@Josh Ja, es funktioniert perfekt und erfordert weniger Tastenanschläge. Ich benutze dieses Konstrukt sehr regelmäßig.
rlf
2
Es ist lustig, wie man die Linux-Shell jahrelang benutzt und trotzdem immer wieder neue Tricks findet
Santiago Arizti
Ich denke, all diese "Tricks" wären offensichtlicher, wenn ich etwas formelles Training in der Bash-Sprache gehabt hätte, aber ich habe gerade genug gelernt, um auszukommen.
Santiago Arizti
6

Der Befehl renamebenennt alle übereinstimmenden Dateien um. Der Hauptzweck besteht darin, mehrere Dateien umzubenennen. Wenn der Perl-Ausdruck jedoch nur einer Datei entspricht, wird nur diese eine Datei umbenannt. Details und Distro spezifischen Syntax lesen Sie bitte die Hilfeseite: man rename.

Anwendungsbeispiel: Benennen Sie "/path/file.txt" in "/path/file.txt.old" um:

rename 's/file.txt/file.txt.old/g' /path/file.txt

Kürzere Notation (dank Shalomb):

rename 's/$/.old/' /path/file.txt
rename '$_.=".old"' /path/file.txt

Für einen Trockenlauf verwenden rename -n.

Weitere Beispiele und Details finden Sie unter https://thepcspy.com/read/bulk-rename-files-in-ubuntu/

Fabian
quelle
cool, ich wusste über den Umbenennungsbefehl Bescheid, wusste nur nie, was alles möglich war, danke!
Santiago Arizti
6
Leider haben verschiedene Linux-Distributionen unterschiedliche renameBefehle mit völlig unterschiedlichem Verhalten.
Kasperd
1
Für diese besondere Aufgabe der Umbenennung durch Anhängen .oldan den Dateinamen, es ist wahrscheinlich ein bisschen bequemer , ein zu tun , rename 's/$/.old/' /path/to/file.txtoderrename '$_.=".old"' /path/to/file.txt
shalomb
@Fabian - Ich habe nicht gepickt, sondern nur nach der "kürzesten Hand" gesucht, nach der die OP anscheinend häufig gesucht hat :)
shalomb
4

Wenn ich in einem Einzelfall mein aktuelles Verzeichnis nicht ändern möchte, verwende ich möglicherweise nur eine Sub-Shell:

(cd dir1/dir2/dir3/ && mv file.txt file.txt.old)

Da Sie sich cdin der Sub-Shell befinden, haben Sie Ihr Verzeichnis in Ihrer tatsächlichen Shell nicht geändert

Adam
quelle
4
Schneller und sicherer zu bedienen && exec mv- auf diese Weise versuchen Sie nicht, die Umbenennung durchzuführen, wenn die cdfehlschlägt und execdie Subshell verbraucht wird, wodurch eine Leistungsbeeinträchtigung vermieden wird.
Charles Duffy
&& Ich stimme dem zu Für einen einmaligen Fall würde ich mir, wie gesagt, keine Sorgen um die Kosten der Unterschale machen (halten Sie es einfach: es ist wichtiger, dass Sie sich leicht merken können, wie es geht, IMO)
Adam
Ich würde argumentieren , dass , wenn Sie nur ein Weg zu erinnern , gehen, hilft die effiziente Art und Weise zu erinnern sicherstellen , dass Sie den ineffizienten Weg in Fällen , die nicht gehen , wo es tut Angelegenheit.
Charles Duffy
4

Ich mag @ archemars Lösung, die {} -Erweiterung zu verwenden, weil Sie sie verwenden können, wenn Sie Ihre Befehlszeile bereits gestartet haben. Hier einige weitere Möglichkeiten zur Vollständigkeit:

F="dir1/dir2/dir3/file.txt" ; mv "$F" "$F.old"

(Anführungszeichen sind nur erforderlich, wenn der Name Leerzeichen oder andere Zeichen enthält, die das Wort brechen.)

mymv() {
    mv "$1/$2" "$1/$3"
}

mymv dir1/dir2/dir3 file.txt file.txt.old
mymv dir5/dir6/dir7 file.txt file.txt.old

Anmerkungen:

  • Dies ist die Bash-Syntax. Möglicherweise verwenden Sie eine andere Shell
  • mymv kann jede sinnvolle Zeichenfolge sein, ich habe mymv für "my move" verwendet.
  • Die Funktionsdefinition kann in Ihrem .bash_profile abgelegt werden

Noch einer:

cd dir1/dir2/dir3 ; mv file.txt file.txt.old ; cd -

aber

(cd dir1/dir2/dir3/ && exec mv file.txt file.txt.old)

(von @Adam und @CharlesDuffy) ist wohl besser, wenn die CD ausfällt.

Law29
quelle
1
Nicht verwenden mmv, es gibt bereits ein Programm mit diesem Namen.
Glglgl
1
@glglgl Fertig :)
Law29
2

Wenn Sie das Unterverzeichnis eingeben möchten, um den Befehl zu verkürzen mv, aber anschließend zum aktuellen Verzeichnis zurückkehren möchten, haben Sie zwei Möglichkeiten. Einer ist, das cdund mvin eine Unterschale zu setzen (wie bereits vorgeschlagen).

Das andere ist, Verzeichnisse zu benutzen pushdund popdzu wechseln:

pushd dir1/dir2/dir3/; mv file.txt file.txt.old; popd

Der pushdBefehl ist wie folgt cd, außer dass zuerst der Name des aktuellen Verzeichnisses auf einen Stapel verschoben wird. popdEntfernt den obersten Namen vom Stapel und wechselt in dieses Verzeichnis.

AndyB
quelle
pushdund popdsind Erweiterungen für die interaktive Verwendung - POSIX listet sie explizit als "Ergebnisse sind nicht spezifiziert" auf, und eine Shell, die zum Ausführen von Skripten (dh in einer minimalen eingebetteten Umgebung) erstellt wurde, muss sie nicht unterstützen.
Charles Duffy
2

Ich würde es einfach tun

cd dir1/dir2/dir3/
mv file.txt file.txt.old
cd ~- # go to the most recent directory
glglgl
quelle
0

Die Lösung beinhaltet: mv something{.txt,.txt.old}Verwenden Sie einen "Bashismus". Wenn Sie eine portablere Möglichkeit wünschen, verwenden Sie allgemeine Variablenmanipulationen:

# rename all files "file*.txt" of directory /dir1/dir2/dir3 into file*.txt.old:
for f in dir1/dir2/dir3/file*.txt ; do
  mv "$f" "${f/.txt/.txt.old}"  # note there are no terminating "/"
done


# "${var/A/B}" is the content of var with the first occurence of "A" replaced by "B"
Olivier Dulac
quelle
2
Siehe pubs.opengroup.org/onlinepubs/009695399/utilities/... für die zugehörige POSIX - Spezifikation - ${var/text/replacement}ist ein bashism selbst.
Charles Duffy
@CharlesDuffy oh ... Du machst mich traurig :(
Olivier Dulac