Jag vill byta namn på flera filer i samma katalog med Bash-skript. Filernas namn är som följer:
file2602201409853.p file0901201437404.p file0901201438761.p file1003201410069.p file2602201410180.p
Jag vill byta namn till följande format:
file2503201409853.p file2503201437404.p file2503201438761.p file2503201410069.p file2503201410180.p
Jag läste om kommandot byta namn och försök göra det på det här sättet, men det gör ingenting, jag tror att jag har frågor om syntaxen. Sedan läste jag att du kan skapa en loop med kommandot mv enligt följande:
for file in cmpsms*2014*.p; do mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}" done
Men jag kan inte byta namn på filerna. Vad gör jag fel?
Kommentarer
Svar
Du hade rätt att överväga att byta namn först. Syntaxen är lite konstig om du inte är van vid regexer men den är den överlägset snabbaste / kortaste vägen när du vet vad du gör:
rename "s/\d{4}/2503/" file*
Det matchar helt enkelt de fyra första siffrorna och byter dem mot de du angav.
Och en testkabel (-vn
betyder att vara måttlig men inte ”t gör vad som helst) med dina filnamn:
$ rename "s/\d{4}/2503/" file* -vn file0901201437404.p renamed as file2503201437404.p file0901201438761.p renamed as file2503201438761.p file1003201410069.p renamed as file2503201410069.p file2602201409853.p renamed as file2503201409853.p file2602201410180.p renamed as file2503201410180.p
Kommentarer
- Obs att detta är Perl-bytet på Debian och derivat (Ubuntu, Mint, …). I andra Linux-distributioner är
rename
ett helt annat filnamnverktyg (som Debian skickas somrename.ul
). - Om din distributiva brist på ett sådant verktyg, titta på @Michael Campbell svar. Jag tror att varje distributör ersätter standard
rename
som debian gjorde.
Svar
Detta borde göra tricket:
for f in file*; do mv $f ${f/${f:4:8}/25032014}; done
Det ersätter strängen mellan 4: e och 12: e tecknet med ”25032014”.
Kommentarer
- den här
for f in file*; do mv $f ${f/${f:4:4}/2503}; done
fungerar också. - Att ' s trevligt. Om du bara vill göra ett ord för ordbyte, fungerar det som sed. t.ex.
for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
- @Eric – Jag har lagt upp ditt svar som ett alternativ eftersom jag tycker att det ' är tydligare och elegantare . Om du också vill lägga upp det som ett svar – <
raderar jag mitt. Tack!
Svar
det här är verkligen @Erics svar uppifrån – men det är ett elegant svar så Jag lägger om det som ett ordentligt svar för att få mer uppmärksamhet åt det.
for f in *Huge*; do mv "$f" "${f/Huge/Monstrous}"; done
Svar
ptrn="file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p" path=/dir ( set -- "${path}/"${ptrn} ; for f ; do { echo "mv ${path}/${f} \ ${path}/file25032014${f#2014}" } ; done )
Detta borde göra tricket. Obs! Jag har inte för vana att överlämna mass-mv-kommandon – som skrivet är det bara ett eko. Du” Jag måste reda ut det innan det kommer att fungera.
Svar
Ett enkelt inbyggt sätt att göra det utan looping, med katalogtrafik :
find -type f | xargs -I {} mv {} {}.txt
Den byter namn varje filen på plats.
Och under ett verk ing exempel med parallellisering :
find -name "file*.p" | parallel "f="{}" ; mv -- {} ${f:0:4}2503${f:8}"
Kommentarer
- Det var en lätt första metod att föreställa sig en bättre lösning. Om du vill ha ett fungerande kommando gör du:
-
find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
Svara
Om du tycker att du gör den här typen mycket, leta upp ”rename.pl”. Det är ett perl-skript, men låter dig helt enkelt mata det perl-kod (som /// expression), och det kommer att göra ett massbyte baserat på det uttrycket eller koden.
Det finns en grundversion här: http://stackoverflow.org/wiki/Rename.pl men det finns andra versioner som flyter runt nätet. Det har funnits i åldrar och åldrar och åldrar.
*
är?