2016-04-27 25 views
3

Ich habe eine Reihe von Dateien, die einfach nur eine Unix-Zeit sind. Das Problem ist, dass ihre Dateinamen zu Millis gehen und das Programm, das das Verzeichnis durchsucht, erwartet, dass sie in Sekunden sind. Also muss ich alle Dateien umbenennen, um die letzten 3 Ziffern vor der Erweiterung .txt zu entfernen. IE:Bash Regex Dateien umbenennen

1461758015598.txt -> 1461758015.txt

Ich bin neu in regex und bash so sicher, ich bin nicht, wie dies zu tun.

+0

A auf bash Version hängt Failsafe Python Alternative, die rekursiv funktioniert: http://Stackoverflow.com/a/39698169/191246 – ccpizza

Antwort

3

Hier ist eine Art und Weise:

for f in *.txt; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

Zwischen dem do und done, ist es bei einer Datei zu einem Zeitpunkt suchen, und der Name der aktuellen Datei im Paramter f. "$f" ist der Wert dieses Parameters, unverändert. "${f/[0-9][0-9][0-9].txt/.txt}" ist der Wert des Parameters, für den eine Substitution angewendet wurde: ersetzen Sie "drei Ziffern gefolgt von .txt" mit nur .txt.

Wie @anubhava wies darauf hin, wenn Sie es ausführen mehr als einmal es lopping Ziffern aus den Dateinamen zu halten, so tun das nicht. Sie können es idempotent machen, indem Sie das Glob-Muster straffen. Dies ist ein wenig sperrig:

for f in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

So könnten Sie ein externes Tool verwenden, um es kompakter zu machen (dies setzt voraus, es gibt keine Leerzeichen oder Zeilenumbrüche in beliebigen Dateinamen im Verzeichnis):

for f in $(ls -1 | egrep '^[0-9]{13}\.txt$'); do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

Sie können die Beschränkung auf nur „ohne Zeilenumbrüche“ reduzieren, indem eine while read Schleife:

ls -1 | egrep '^[0-9]{13}\.txt$' | while read f; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 
+4

OP muss nur einmal ausgeführt werden oder es wird auch '1461758015.txt' in' 1461758.txt' umbenennen und dann '1461758.txt 'nach' 1461.txt' – anubhava

+0

If die OPs benutzen bash trotzdem, extglob mit 'ls + ([0-9]). txt | egrep ... könnte sicherer und leistungsfähiger in großen Verzeichnissen sein. – ghoti

0

Mark Antwort deckt eine Reihe von Optionen.

Aber wenn Sie wollen etwas rekursiv, ich mit einer find basierten Lösung so gehen würde:

find -E . -regex '.*/[0-9]{13}\.txt' -exec \ 
    sh -c 'set -; mv -v "$0" "${0%???.txt}.txt"' "{}" \; 

Hinweise:

  • Ich bin mit FreeBSD, die eine -E Option muss Teilen Sie -regex mit, um ERE zu verwenden. Wenn Sie ein älteres Betriebssystem verwenden, müssen Sie das ERE möglicherweise in BRE konvertieren.
  • Das ERE besteht auf 13 Ziffern. Dies erspart Ihnen die Bedenken von anubhava, die Verringerung zu erhöhen, wenn Sie die Conversion mehr als einmal ausführen.
  • Für die Parametererweiterung verwende ich ${..%..} anstelle von ${../../}, so dass diese POSIX-konforme und nicht abhängig von bash. (Es funktioniert natürlich auch in bash, es muss einfach nicht.)
  • Sie fragen sich vielleicht, warum die Übereinstimmung einfach einzelne Platzhalterzeichen anstelle von Ziffern entfernt. Das ist in Ordnung - einfacher für mich zu schreiben, und wir haben bereits die Dateinamenbeschränkung als Teil der Optionen auf find festgelegt.

Wenn Sie mit find zu vermeiden, würde es vorziehen, aber in bash noch rekursive etwas wollen, könnten Sie die globstar Option:

shopt -s globstar extglob 
for f in **/+([0-9]).txt; do 
    [[ $f =~ ^[0-9]{13}\.txt$ ]] && mv -v "$f" "${f%...\.txt}.txt" 
done 

Beachten Sie, dass globstar 4.