Warum verhält sich „Umbenennen“ anders, wenn ich den vollständigen Pfad statt des aktuellen Pfads verwende?

Warum verhält sich „Umbenennen“ anders, wenn ich den vollständigen Pfad statt des aktuellen Pfads verwende?

Ok, ich binBeantwortung einer Fragewobei der OP mehrere Repositories in Ubuntu hat, die möglicherweise Probleme bei der Installation nicht verwandter Software verursachen. Ich empfehle, die PPAs mit einem einzigen Liner zu deaktivieren renameund dann einer Reihe von Anweisungen zu folgen. Alles in Ordnung, und ich lasse diese Frage einfach als beantwortet stehen ... nein. Ergebnisse, die renamesich nicht wie erwartet verhalten haben:

sudo rename s/list/list\.disable/g /etc/apt/sources.list.d/*.list

Damit erwarte ich, dass rename /etc/apt/sources.list.d/alle Dateien mit der Endung durchsucht .listund durch ersetzt .list. .list.disableIch hatte eine andere Antwort mit fast demselben Befehl, aber OP hat nie Feedback gegeben, und ich werfe die Theorie sozusagen in den Raum, ohne sie vorher zu testen. Daher bin ich überrascht, dass OP Probleme mit der Zeile hat:

Can't rename /etc/apt/sources.list.d/iaz-battery-status-quantal.list /etc/apt/sources.list.disable.d/iaz-battery-status-quantal.list.disable: No such file or directory
Can't rename /etc/apt/sources.list.d/ubuntu-wine-ppa-quantal.list /etc/apt/sources.list.disable.d/ubuntu-wine-ppa-quantal.list.disable: No such file or directory
Can't rename /etc/apt/sources.list.d/webupd8team-java-raring.list /etc/apt/sources.list.disable.d/webupd8team-java-raring.list.disable: No such file or directory

Ich habe ein komisches Gefühl, also teste ich die Theorie selbst und sehe das gleiche Ergebnis. Dann,wenn Sie ein Problem haben, ist in der Regel regex, keine? Ich habe den regulären Ausdruck auf so viele verdrehte Arten geändert:

  • s/.list/.list.disable/g
  • s/.list/.list.disable/g
  • /list/list.deaktivieren/
  • andere Kombinationen, an die ich mich nicht erinnere

Nun, ich entschied, dass Regex nicht das Problem war, also starrte ich auf den Selektor, änderte ihn /etc/apt/sources.list.d/*und wiederholte den Regex-Test. Keine Freude. Etwas frustriert tue ich es touch some.listund wende meinen Befehl an

rename s/\.list/\.list\.disable/g *

Bingo! Jetzt fühle ich mich wie ein Troll. Ich korrigiere meine Antwort und mache mit meinem Leben weiter ... nein! Das ist nicht akzeptabel. Warum? Ich schaue im Handbuch nach, das zu meiner Überraschung nur aktuelle Pfadbeispiele verwendet. Ist das normal? Oder liegt es einfach daran, dass die Funktion nicht implementiert wurde? Oder sollte ich anfangen, meinen Theorien zu misstrauen?

Antwort1

Verwenden Sie den Parameter, um einen Probelaufmodus -nauszuführen , der sehr hilfreich ist, wenn Sie Ihr Muster testen möchten:rename

martin@martin ~ % rename -n s/list/list.disable/g /etc/apt/sources.list.d/*.list | sed 's/renamed as/\n =>/g'
[...]
/etc/apt/sources.list.d/spotify.list 
 => /etc/apt/sources.list.disable.d/spotify.list.disable
/etc/apt/sources.list.d/steam.list 
 => /etc/apt/sources.list.disable.d/steam.list.disable
[...]

Der offensichtliche Fehler besteht hier darin, dass das Muster listübereinstimmt und Sie daher versuchen, sowohl den Ordner als auch die darin enthaltenen Dateien umzubenennen.sources.list.d

Verwenden Sie stattdessen dieses Muster:

rename -n 's/\.list$/.list.disable/' /etc/apt/sources.list.d/*.list | sed 's/renamed as/\n =>/g'
[...]
/etc/apt/sources.list.d/spotify.list 
 => /etc/apt/sources.list.d/spotify.list.disable
/etc/apt/sources.list.d/steam.list 
 => /etc/apt/sources.list.d/steam.list.disable
[...]

Die Unterschiede sind:

  1. Durch das Anführen des Punkts .im Suchmuster \.wird sichergestellt, dass der Punkt nur mit einem echten Punkt übereinstimmt und nicht mit einem beliebigen Zeichen (das ist die normale Wirkung eines nicht in Anführungszeichen gesetzten Punkts in einem regulären Ausdruck).

  2. Die $After-List bedeutet „Ende der Zeichenfolge“. Sie stellt sicher, dass nur die „.list“ am Ende des Dateinamens übereinstimmt und ersetzt wird, nicht eine „.list“, die sich irgendwo anders im Pfad oder Dateinamen befindet.

  3. Im Ersetzungsstring braucht man den Punkt nicht in Anführungszeichen zu setzen, ".list.disable" kommt deshalb auch ohne Backslash aus, da dieser .dort keine besondere Bedeutung mehr hat.

  4. Beachten Sie auch, dass ich den regulären Ausdruck in einfache Anführungszeichen gesetzt habe, um zu verhindern, dass die Shell ihn in irgendeiner Weise ändert.

Antwort2

Das Problem besteht darin, den globalen Schalter zu verwenden, gobwohl Sie stattdessen eigentlich das Muster hätten verankern sollen. So wie Sie es geschrieben haben:

s/a/b/g

ersetzt überall in der Zeichenfolge jedes a durch b. Dies führt dazu, dass Sie versuchen, Pfade umzubenennen, für die kein Verzeichnis vorhanden ist. Dies ist auch der Grund, warum das Problem verschwand, als Sie den Vorgang innerhalb des Verzeichnisses ausführten, sodass nur eine Übereinstimmung zum Ersetzen vorhanden war.

Ich denke, Sie wollten vielleicht das Muster verankern

s/\.list$/.list.disable/

Dies hätte den Versuch verhindert, eine Datei in das nicht vorhandene Verzeichnis /etc/apt/sources.list.disable.d/ zu verschieben (deshalb können Sie keine Datei dorthin verschieben).

verwandte Informationen