![Alle Dateinamen mit einer bestimmten Anzahl von Zeichen abrufen](https://rvso.com/image/109243/Alle%20Dateinamen%20mit%20einer%20bestimmten%20Anzahl%20von%20Zeichen%20abrufen.png)
Ich möchte alle Dateinamen ändern, die genau die Länge von 16 Zeichen (Ziffern und Kleinbuchstaben) haben. Ich habe es mit [0-9a-z]{16}
und [0-9a-z]\{16\}
für den Platzhalter regX
im folgenden Snippet versucht, aber es funktioniert nicht.
for file in <regX>
do
mv "$file" "${file}.txt"
done
Antwort1
Shell-Globbing-Mustersind keine regulären AusdrückeSie sehen zwar ähnlich aus, funktionieren aber in mancher Hinsicht ganz unterschiedlich.
Der reguläre Ausdruck [0-9a-z]{16}
stimmt mit einer Zeichenfolge überein, die eine Folge von 16 Zeichen des genannten Zeichenbereichs enthält (die Zeichenfolge mit der Übereinstimmung kann länger sein).
Das entsprechende Shell-Globbing-Muster wäre etwa wie folgt
*[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]*
Das ist weil
- Globbing-Muster unterstützen keine Modifikatoren wie „das vorherige N-mal wiederholen“.
- Globbing-Muster sind standardmäßig am Anfang und Ende verankert. Deshalb habe ich
*
am Anfang und Ende des Musters eingefügt. A*
entspricht einer beliebigen Anzahl beliebiger Zeichen. Entfernen Sie diese, wenn Sie übereinstimmen möchtengenau16 Zeichen.
[0-9a-z]
Sie können mit Perl eine Zeichenfolge aus 16 Zeichen erstellen :
$ pattern="$( perl -e 'print "[0-9a-z]" x 16' )"
Mit bash
können Sie über alle Namen im aktuellen Verzeichnis iterieren und dann testen, ob die Namen mit Ihrem regulären Ausdruck übereinstimmen:
for name in *; do
if [[ -f "$name" ]] && [[ "$name" =~ ^[0-9a-z]{16}$ ]]; then
echo mv "$name" "$name.txt"
fi
done
Entfernen Sie es, echo
sobald Sie sicher sind, dass es das Richtige tut.
Beachten Sie, dass ich das Muster verankert habe, sodass längere Namen nicht übereinstimmen. Mit dem -f
Test stelle ich außerdem sicher, dass die Namen, die wir erhalten, tatsächlich nur die von regulären Dateien sind.
Antwort2
Mitextglob
shopt -s extglob
for file in +([0-9a-z])
do
[[ ${#file} == 16 ]] && echo mv "$file" "${file}.txt"
done
+([0-9a-z])
bedeutet ein oder mehrere[0-9a-z]
Zeichen${#file}
gibt die Länge des Dateinamens anecho
ist für den Probelauf, entfernen Sie, sobald alles in Ordnung ist
Antwort3
Wenn Sie über perl-rename verfügen (wird rename
auf Debian-basierten Systemen aufgerufen, perl-rename
auf anderen), können Sie Folgendes tun:
perl-rename -n 's/^[0-9a-z]{16}$/$&.txt/' *
Wenn das das gewünschte Ergebnis bringt, entfernen Sie das , -n
damit die Dateien tatsächlich umbenannt werden. Die Syntax von perl-rename
ist ein Perl-Befehl. Hier verwenden wir den Substitutionsoperator ( ), der durch s/from/to/
ersetzt . Das ist in diesem Fall Ihr regulärer Ausdruck und das ist die spezielle Variable , die „was auch immer übereinstimmt“ bedeutet, plus die Erweiterung .from
to
from
to
$&
.txt
Um dies mit einem Shell-Glob zu tun (verwenden Sie@Kusalanandasoder@SundeepsAnsatz, dies dient nur der Vollständigkeit):
for f in [0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]; do
mv -- "$f" "$f".txt
done
Mit GNU find
:
find . -regextype posix-extended -regex '.*/[0-9a-z]{16}' -exec mv {} {}".txt" \;
Antwort4
L16=$(csh -c 'repeat 16 echo -n "?"')
find . -name "$L16" ! -name '*[!0-9a-z]*' -exec sh -c '
mv "$1" "$1.txt"
' {} {} \;