¿Cómo poner a cero los números del relleno en los nombres de archivos en Bash?

StackOverflow https://stackoverflow.com/questions/55754

  •  09-06-2019
  •  | 
  •  

Pregunta

¿Cuál es la mejor manera, usando Bash, de cambiar el nombre de los archivos en el formulario:

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

Con nombres de archivos rellenos con ceros:

(foo00001, foo00002, ..., foo01300, ..., fooN)
¿Fue útil?

Solución

En caso N no está fijado a priori:

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

Otros consejos

No es bash puro, pero es mucho más fácil con el rename dominio:

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

Tuve un caso más complejo en el que los nombres de los archivos tenían un sufijo además de un prefijo.También necesitaba realizar una resta del número del nombre del archivo.

Por ejemplo, quería foo56.png convertirse foo00000055.png.

Espero que esto ayude si estás haciendo algo más complejo.

#!/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

El comando oneline que uso es este:

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

PATRÓN puede ser por ejemplo:

  • cambiar el nombre con contador incremental: %04d.${f#*.} (mantenga la extensión del archivo original)
  • cambiar el nombre con contador incremental con prefijo: photo_%04d.${f#*.} (mantenga la extensión original)
  • cambie el nombre con el contador de incrementos y cambie la extensión a jpg: %04d.jpg
  • cambiar el nombre con contador de incrementos con prefijo y nombre base del archivo: photo_$(basename $f .${f#*.})_%04d.${f#*.}
  • ...

Puede filtrar el archivo para cambiarle el nombre, por ejemplo ls *.jpg | ...

Tienes disponible la variable f ese es el nombre del archivo y i ese es el mostrador.

Para su pregunta el comando correcto es:

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

Pure Bash, sin procesos externos distintos de '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

Lo siguiente lo hará:

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

EDITAR: cambiado para usar ((i=1,...)), gracias mweerden!

Aquí hay una solución rápida que supone un prefijo de longitud fija (su "foo") y un relleno de longitud fija.Si necesita más flexibilidad, tal vez este sea al menos un punto de partida útil.

#!/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

Mi solución reemplaza los números, en todas partes en una cuerda

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

Puede probarlo fácilmente, ya que simplemente imprime nombres de archivos transformados (no se realizan operaciones en el sistema de archivos).

Explicación:

Recorriendo la lista de archivos

Un bucle: for f in * ; do ;done, enumera todos los archivos y pasa cada nombre de archivo como $f variable al cuerpo del bucle.

Agarrando el número de la cuerda

Con echo $f | sed canalizamos la variable $f a sed programa.

En comando sed 's/[^0-9]*//g', parte [^0-9]* con modificador ^ le indica que coincida con el dígito opuesto del 0 al 9 (no un número) y luego lo elimine con un reemplazo vacío //.¿Por qué no simplemente eliminar [a-z]?Porque el nombre del archivo puede contener puntos, guiones, etc.Entonces, quitamos todo lo que no es un número y obtenemos un número.

A continuación asignamos el resultado a number variable.Recuerde no poner espacios en la tarea, como number = …, porque obtienes un comportamiento diferente.

Asignamos el resultado de la ejecución de un comando a una variable, envolviendo el comando con los símbolos de acento grave `.

relleno cero

Dominio printf "%04d" $number cambia el formato de un número a 4 dígitos y agrega ceros si nuestro número contiene menos de 4 dígitos.

Reemplazo de número por número relleno con ceros

Usamos sed nuevamente con comando de reemplazo como s/substring/replacement/.Para interpretar nuestras variables, utilizamos comillas dobles y sustituimos nuestras variables de esta manera. ${number}.


El script anterior simplemente imprime nombres transformados, así que hagamos el trabajo de cambio de nombre real:

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

Espero que esto ayude a alguien.

Pasé varias horas para resolver esto.

Para rellenar números a la izquierda en los nombres de archivos:

$ 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

Explicación

for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
  • tenga en cuenta las comillas invertidas: `echo ... $2}\` (La barra invertida, \, inmediatamente arriba simplemente divide esa línea en dos líneas para facilitar la lectura)
  • en un bucle, busque archivos nombrados como números con extensiones de alfabeto en minúsculas: [0-9]*.[a-z]*
  • repetir ese nombre de archivo ($f) para pasarlo a awk
  • -F. : awk separador de campo, un punto (.):si coincide, separa los nombres de los archivos en dos campos ($1 = número; $2 = extensión)
  • formato con printf:imprimir el primer campo ($1, la parte numérica) como 4 dígitos (%04d), luego imprima el período, luego imprima el segundo campo ($2:la extensión) como una cadena (%s).Todo eso está asignado a la $tmp variable
  • Por último, mueva el archivo fuente ($f) al nuevo nombre de archivo ($tmp)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top