Byt namn på flera filer med Bash-skript

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

  • möjlig duplikat av Hur kan jag byta namn mycket av filer som använder en regex?
  • Du kan ' t ha ett mönsteruttryck till höger om ett parameterutvidgningsersättningsuttryck. Vad förväntade du dig att där * är?
  • @Kiwy Den frågan handlar om att ta bort en del av filnamnet. Ergo, mycket tvivelaktigt duplicerad.
  • Nästa gång, beskriv filändringsändringarna du vill göra (jag var tvungen att titta på det här rätt innan jag såg skillnaderna och likheterna). Exempel är bra, men en beskrivning liksom exempel är ännu bättre.

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 som rename.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!

  • Varför saknar dubbla citat ?
  • Det ger mig ett fel: " mv: target ' FILE_NAME ' är inte en katalog "
  • 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.

    Lämna ett svar

    Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *