UNIX :: Padding per i file contenenti string e multipleNumber
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
Con lo standalone rename
o il prename
comando 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
.
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 printf
comando viene utilizzato per formattare il secondo gruppo con spaziatura zero, quattro cifre larghe.
Usa una regex per estrarre le sottostringhe pertinenti dall'input e poi riempila ...
- Per ogni file.
- Estrai il prefisso, il numero e il suffisso dal nome del file.
- Riempi il numero con zeri.
- Crea il nuovo nome file.
- 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
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