Domanda

Qual è il modo migliore, usando Bash, per rinominare i file nel formato:

(foo1, foo2, ..., foo1300, ..., fooN)

Con nomi di file preceduti da zero:

(foo00001, foo00002, ..., foo01300, ..., fooN)
È stato utile?

Soluzione

Nel caso N non è fissato a priori:

 for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done

Altri suggerimenti

Non è puro bash, ma molto più semplice con il file rename comando:

rename 's/\d+/sprintf("%05d",$&)/e' foo*

Ho avuto un caso più complesso in cui i nomi dei file avevano un suffisso oltre a un prefisso.Avevo anche bisogno di eseguire una sottrazione del numero dal nome del file.

Ad esempio, volevo foo56.png diventare foo00000055.png.

Spero che questo ti aiuti se stai facendo qualcosa di più complesso.

#!/bin/bash

prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8

for file in ${prefix}[0-9]*${postfix}; do
  # strip the prefix off the file name
  postfile=${file#$prefix}
  # strip the postfix off the file name
  number=${postfile%$postfix}
  # subtract 1 from the resulting number
  i=$((number-1))
  # copy to a new name with padded zeros in a new folder
  cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done

Il comando oneline che utilizzo è questo:

ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done

IL MODELLO può essere ad esempio:

  • rinominare con incremento contatore: %04d.${f#*.} (mantieni l'estensione del file originale)
  • rinominare con incremento contatore con prefisso: photo_%04d.${f#*.} (mantenere l'estensione originale)
  • rinomina con contatore di incremento e modifica l'estensione in jpg: %04d.jpg
  • rinominare con contatore di incremento con prefisso e nome base del file: photo_$(basename $f .${f#*.})_%04d.${f#*.}
  • ...

Puoi filtrare il file da rinominare, ad esempio ls *.jpg | ...

Hai a disposizione la variabile f questo è il nome del file e i quello è il contatore.

Per la tua domanda il comando giusto è:

ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done

Pure Bash, nessun processo esterno diverso da "mv":

for file in foo*; do
  newnumber='00000'${file#foo}      # get number, pack with zeros
  newnumber=${newnumber:(-5)}       # the last five characters
  mv $file foo$newnumber            # rename
done

Quanto segue lo farà:

for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done

MODIFICARE: cambiato in usare ((i=1,...)), grazie mweerden!

Ecco una soluzione rapida che presuppone un prefisso di lunghezza fissa (il tuo "foo") e un'imbottitura di lunghezza fissa.Se hai bisogno di maggiore flessibilità, forse questo sarà almeno un utile punto di partenza.

#!/bin/bash

# some test data
files="foo1
foo2
foo100
foo200
foo9999"

for f in $files; do
    prefix=`echo "$f" | cut -c 1-3`        # chars 1-3 = "foo"
    number=`echo "$f" | cut -c 4-`         # chars 4-end = the number
    printf "%s%04d\n" "$prefix" "$number"
done

La mia soluzione sostituisce i numeri, ovunque in una stringa

for f in * ; do
    number=`echo $f | sed 's/[^0-9]*//g'`
    padded=`printf "%04d" $number`
    echo $f | sed "s/${number}/${padded}/";
done

Puoi provarlo facilmente, poiché stampa solo i nomi dei file trasformati (non vengono eseguite operazioni sul filesystem).

Spiegazione:

Scorrendo l'elenco dei file

Un ciclo continuo: for f in * ; do ;done, elenca tutti i file e passa ciascun nome file come $f variabile al corpo del loop.

Prendendo il numero dalla stringa

Con echo $f | sed conduciamo la variabile $f A sed programma.

Al comando sed 's/[^0-9]*//g', parte [^0-9]* con modificatore ^ dice di abbinare la cifra opposta alla cifra 0-9 (non un numero) e quindi rimuoverla con la sostituzione vuota //.Perché non semplicemente rimuovere [a-z]?Poiché il nome file può contenere punti, trattini, ecc.Quindi, eliminiamo tutto ciò che non è un numero e otteniamo un numero.

Successivamente, assegniamo il risultato a number variabile.Ricorda di non inserire spazi nell'assegnazione, come number = …, perché ottieni un comportamento diverso.

Assegniamo il risultato dell'esecuzione di un comando alla variabile, avvolgendo il comando con i simboli backtick `.

Imbottitura zero

Comando printf "%04d" $number cambia il formato di un numero in 4 cifre e aggiunge zeri se il nostro numero contiene meno di 4 cifre.

Sostituzione del numero con un numero riempito con zero

Noi usiamo sed di nuovo con il comando sostitutivo come s/substring/replacement/.Per interpretare le nostre variabili, utilizziamo virgolette doppie e sostituiamo le nostre variabili in questo modo ${number}.


Lo script sopra stampa semplicemente i nomi trasformati, quindi eseguiamo il vero lavoro di ridenominazione:

for f in *.js ; do
    number=`echo $f | sed 's/[^0-9]*//g'`
    padded=`printf "%04d" $number`
    new_name=`echo $f | sed "s/${number}/${padded}/"`
    mv $f $new_name;
done

Spero che questo aiuti qualcuno.

Ho impiegato diverse ore per capirlo.

Per inserire i numeri a sinistra nei nomi dei file:

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz

$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10

Spiegazione

for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
  • nota gli apici inversi: `echo ... $2}\` (La barra rovesciata, \, immediatamente sopra divide semplicemente quella riga su due righe per facilitare la leggibilità)
  • in un ciclo trova i file denominati come numeri con estensioni alfabetiche minuscole: [0-9]*.[a-z]*
  • echo quel nome file ($f) a cui passarlo awk
  • -F. : awk separatore di campo, un punto (.):se corrispondente, separa i nomi dei file in due campi ($1 = numero; $2 = estensione)
  • formato con printf:stampa il primo campo ($1, la parte numerica) come 4 cifre (%04d), quindi stampa il punto, quindi stampa il secondo campo ($2:l'estensione) come una stringa (%s).Tutto ciò è assegnato a $tmp variabile
  • infine, sposta il file sorgente ($f) al nuovo nome file ($tmp)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top