Muszę zmienić nazwę zestawu plików, używając rename
polecenia (z wyrażeniem regularnym). Po kilku próbach nie jestem w stanie znaleźć wyrażenia, które uzyska oczekiwany wynik.
Mam taki wzór pliku:
prefix_ some_name _other.txt
Wszystkie pliki zaczynają się od „ prefix_
” i kończą się na „ _other.txt
”, a część some_name może składać się z wielu (alfanumerycznych) słów oddzielonych podkreślnikami. Możliwe jest więc:
prefix_one_name_other.txt
prefix_this_is_my_name_1_this1_other.txt
Muszę zmienić nazwy takich plików:
other_one-name_ datetime other_this-is-my-name-1-this1_ datetime
Innymi słowy:
- Musisz usunąć „
prefix
” (pozostawiając podkreślenie) other
Token „ ” przechodzi na początek nazwy pliku- W some_name przekonwertuj podkreślenie (_) na myślnik (-)
- Znak podkreślenia na końcu nazwy pliku (po jakiejś nazwie ) musi pozostać
- Musisz usunąć
.txt
rozszerzenie, zastąpione datetime .
Co próbowałem:
rename 's/fw_([a-z]+)_(\d)_(\w+\d)_(\w+)\.txt/$4_$1-$2-$3_'$datahora'/' *.txt
$datahora
ma wartość daty / godziny (przetestowano). Działa to zgodnie z oczekiwaniami
prefix_name_1_gnt1_other.txt
ale nie z
prefix_other_name_2_gnt2_other.txt
Gdzie popełniłem błąd? Jak inaczej mogę to osiągnąć?
Zawiesiłem zdanie, ponieważ na razie nie jestem w stanie znaleźć wyrażenia regularnego, które działałoby dla wszystkich posiadanych nazw plików. Wiem, że pierwszy element w ciągu jest zawsze prefix
częścią, a ostatni element jest wtedy other.txt
częścią ciągu. Możliwe jest podzielenie łańcucha na tablicę i uzyskanie elementów potrzebnych do zbudowania nowej nazwy. W rzeczywistości coś takiego.
datahora="20140718-080000"
arrfiles=( *.txt )
for curfile in ${arrfiles[*]}
do
arrparts=( ${curfile//_/ } )
numitems=${#arrparts[*]}
newname=""
for (( c=1; c<numitems-1; c++ ))
do
newname+="${arrparts[c]}-"
done
newname=${newname%-}
arrparts[numitems-1]=${arrparts[numitems-1]/.txt/}
newname="${arrparts[numitems-1]}_${newname}_$datahora"
echo "$curfile pasa a $newname"
mv ${curfile} ${newname}
done
Po zrobieniu tego w ten sposób, spróbowałem ponownie @peterph sugestię, a na koniec skończyłem z kilkoma kombinacjami regexów. Pomyśl coś takiego:
rename 's/_/-/g' *.txt
rename 's/^fw-(.*)-([^-]*)(\.txt)/$2.$1$3/' *.txt
rename 's/(\w+)\.(.*)(\.txt)/$1_$2_'$datahora'/' *.txt
Nie jestem pewien, jakie jest najlepsze podejście. Moim zdaniem wariant wyrażenia regularnego wydaje się bardziej elegancki, ale potrzebuję trzech operacji zmiany nazwy (dostępu trzy razy na dysk), aby wykonać pracę, podczas gdy array
wariant zapisuje tylko raz na dysku.
¿Co sądzisz o tych dwóch rozwiązaniach? ...
Dzięki jeszcze raz.