UNIX :: Padding per i file contenenti string e multipleNumber

Aug 23 2020

Ho molti file che non hanno nomi di file coerenti.

Per esempio

IMG_20200823_1.jpg
IMG_20200823_10.jpg
IMG_20200823_12.jpg
IMG_20200823_9.jpg

Vorrei rinominare tutti loro e assicurarmi che seguano tutti la stessa convenzione di denominazione

IMG_20200823_0001.jpg
IMG_20200823_0010.jpg
IMG_20200823_0012.jpg
IMG_20200823_0009.jpg

Ho scoperto che è possibile modificare per file che hanno solo un numero utilizzando di seguito

printf "%04d\n" 

Tuttavia non sono in grado di fare con i miei file considerando che mescolano stringa + "_" + numeri diversi.

Qualcuno può aiutarmi ? Grazie !

Risposte

2 Cyrus Aug 23 2020 at 19:20

Con lo standalone renameo il prenamecomando di Perl :

rename -n 's/(\d+)(\.jpg$)/sprintf("%04d%s",$1,$2)/e' *.jpg

Produzione:

rinomina (IMG_20200823_10.jpg, IMG_20200823_0010.jpg)
rinomina (IMG_20200823_12.jpg, IMG_20200823_0012.jpg)
rinomina (IMG_20200823_1.jpg, IMG_20200823_0001.jpg)
rinomina (IMG_20200823_9.jpg, IMG_20200823_0009.jpg)

se tutto sembra a posto, rimuovi -n.

2 BenjaminW. Aug 23 2020 at 19:19

Con le espressioni regolari di Bash:

re='(IMG_[[:digit:]]+)_([[:digit:]]+)'

for f in *.jpg; do
    [[ $f =~ $re ]]
    mv "$f" "$(printf '%s_%04d.jpg' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}")"
done

dove BASH_REMATCHè un array contenente i gruppi di cattura dell'espressione regolare. All'indice 0 è l'intera partita; l'indice 1 contiene IMG_e il primo gruppo di cifre; l'indice 2 contiene il secondo gruppo di cifre. Il printfcomando viene utilizzato per formattare il secondo gruppo con spaziatura zero, quattro cifre larghe.

1 KamilCuk Aug 23 2020 at 19:15

Usa una regex per estrarre le sottostringhe pertinenti dall'input e poi riempila ...

  1. Per ogni file.
  2. Estrai il prefisso, il numero e il suffisso dal nome del file.
  3. Riempi il numero con zeri.
  4. Crea il nuovo nome file.
  5. Sposta i file

Il codice seguente per bash:

echo 'IMG_20200823_1.jpg
IMG_20200823_10.jpg
IMG_20200823_12.jpg
IMG_20200823_9.jpg' | 
while IFS= read -r file; do  # foreach file
    # Use GNU sed to extract parts on separate lines
    tmp=$(<<<"$file" sed 's/\(.*_\)\([0-9]*\)\(\..*\)/\1\n\2\n\3\n/')
    # Read the separate parts separated by newlines
    {
       IFS= read -r prefix
       IFS= read -r number
       IFS= read -r suffix
    } <<<"$tmp" # create new filename newfilename="$prefix$(printf "%04d" "$number")$suffix" # move the files echo mv "$file" "$newfilename"
done

uscite:

mv IMG_20200823_1.jpg IMG_20200823_0001.jpg
mv IMG_20200823_10.jpg IMG_20200823_0010.jpg
mv IMG_20200823_12.jpg IMG_20200823_0012.jpg
mv IMG_20200823_9.jpg IMG_20200823_0009.jpg
rossifr Aug 24 2020 at 13:02

Restando perplesso dal tuo suggerimento a printf ...

Contenuto della cartella corrente:

$ ls -1 IMG_*
IMG_20200823_1.jpg
IMG_20200823_21.jpg

Sicuramente non è una buona soluzione ma con printf e sed possiamo farlo:

$ printf "mv %3s_%8s_%d.%3s %3s_%8s_%04d.%3s\n" $(ls -1 IMG_* IMG_* | sed 's/_/ /g; s/\./ /')
mv IMG_20200823_1.jpg IMG_20200823_0001.jpg
mv IMG_20200823_21.jpg IMG_20200823_0021.jpg