Gibt es einen Linux-Befehl wie mv, aber mit Regex?

41

Zum Beispiel möchte ich mv (.*?).sql $1.php,

Gibt es einen Befehl, mit dem ich Umbenennungsmuster festlegen kann?

JoshRibs
quelle

Antworten:

32

Wie andere schon erwähnt haben, renameist dies gut, aber lesen Sie die Manpage ( man rename), bevor Sie es versuchen. Es gibt mindestens zwei völlig unterschiedliche Tools, renamedie als solche bezeichnet werden. Welches Tool Sie verwenden, hängt von Ihrer Distribution ab. Ein falscher Anruf kann gefährlich sein.

Hier ist die Manpage für die Perl-basierte Version von Larry Wall, die mit Ubuntu geliefert wird. Sie geben ihm einen Perl-Ausdruck wierename 's/\.sql$/.php/' *.sql

Hier ist die Manpage für die Umbenennung, die mit älteren Red Hat- und CentOS-Distributionen geliefert wird. Die Verwendung ist wie eine einfache Zeichenfolgensubstitutionrename .sql .php *.sql

Sie können auch einen Bash-Einzeiler verwenden, um jede Datei einzeln zu verarbeiten:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Ryan Bright
quelle
Könnte jemand eine Windows-Binärdatei für die perlbasierte Umbenennung hochladen?
Mcandre
Beim Umbenennen der Perl-Version können keine Dateien von einem Dateisystem in ein anderes verschoben werden.
Lilydjwg
bash one-liner ist hilfreich, insbesondere wenn keine renamefunktion (dh busybox)
artm
10

Es gibt rename(1), die keine regulären Ausdrücke verwenden, aber Ihr Problem lösen können:

rename .sql .php *.sql

Es gibt auch mmv(1), aber ich bin mit der Funktionsweise nicht vertraut.

Adam Rosenfield
quelle
In Ubuntu und Debian (bei anderen Distributionen nicht sicher) werden standardmäßig /usr/bin/renameLinks zu verwendet /usr/bin/prename, für die reguläre Ausdrücke erforderlich sind.
ℝaphink
5

Tag auch,

Sie können auch versuchen, etwas einzugeben

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

Oder um es mit Regex zu machen, ändere es leicht in

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

für ein bisschen Spaß beim Shell-Codieren. (-:

Rob Wells
quelle
2
Dies schlägt bei Dateien fehl, deren Name Leerzeichen enthält. Seien Sie also vorsichtig. Man sollte niemals die lsAusgabe analysieren .
Slhck
Das sedBeispiel ist jedoch ziemlich gut.
Bright-Star
2

Als Klempner mag ich Rohre :)

Hinweis: Diese Antwort ist wortreich - als Neuling weiß ich es zu schätzen, wenn sich jemand, der es weiß, die Zeit nimmt, um zu erklären, und ich zahle "vorwärts". Wenn Sie kein Neuling sind, entschuldigen Sie bitte die Länge und Ausführlichkeit.

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

Woher:

ls -1 *_201[67][0-9]*

listet alle Dateien auf, die dem Muster entsprechen, in diesem Fall suche ich nach Dateien mit dem Datum im Dateinamen im Format 'JJJJMMTT'

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1: 1. Erfassungsgruppe - der gesamte Dateiname

^ 2: 2. Erfassungsgruppe - der erste Teil des Dateinamens

^ 3: 3. Erfassungsgruppe - der 2. Dateinamenteil - hier das Datum als 'JJJJMMTT'

^ 4: 4. Erfassungsgruppe - optionaler Dateinamenteil zwischen dem Datum und der Erweiterung sowie der Erweiterung selbst

Sooooo .... wenn ich eine Datei mit dem Namen habe

CallLog_555123412_20161231-214403.7z

...dann

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

heißt eigentlich

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

Beachten Sie, dass die Ausgabe des Befehls sed zur Ausführung an 'bash' weitergeleitet wird. Um zuerst zu sehen, ob die vorgeschlagene Datei verschoben wird, OHNE sie tatsächlich zu verschieben, entfernen Sie zuerst das Zeichen '| bash 'am Ende und versuche es so:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

Hierdurch werden keinerlei Änderungen vorgenommen, es wird jedoch der Befehl angezeigt, der ausgeführt wird, wenn Sie ihn mit '| ausführen Bash 'markiert am Ende.

Dies ist nützlich, da Sie beliebige Unterverzeichnisse aus Teilen des Dateinamens oder anderen Elementen erstellen können, die Sie im Befehl sed zum Ersetzungstext hinzufügen. Beachten Sie jedoch, dass sed viele Escape-Zeichen erfordert.

SED Regex Klammern:

(...) für Capture-Gruppierung Escape-Zeichen erforderlich -> \ (... \)

{m, n} müssen zur Quantifizierung des vorherigen Objekts ausgeblendet werden -> \ {m, n \}

/ erfordert ein Escapezeichen in der Ersatzzeichenfolge -> \ /

[...] Für Zeichenklassen ist KEIN Escape-Befehl erforderlich

\ 1 in der Ersatzzeichenfolge bezieht sich auf die erste erfasste Gruppe usw.

SICHERHEITSHINWEIS: PFEIFEN SIE NIEMALS, WENN SIE DAS ERGEBNIS NICHT VOLLSTÄNDIG VERSTEHEN ...

Hoffe das hilft ein paar Blockaden zu beseitigen :)

Skeetastax
quelle
1

Installieren Sie mmvund führen Sie dann Folgendes aus:

mmv "*.sql" "#1.php"
Gepsens
quelle