¿Cómo cambiar el nombre de varios archivos secuencialmente desde la línea de comandos?

15

Cómo cambiar el nombre del archivo a continuación

AS1100801000002.RAW7AGS 
AS1100801001008.RAW7AH4
AS1100801002001.RAW7AH9
AS1100801003002.RAW7AHE
AS1100801004009.RAW7AHT
AS1100801005002.RAW7AHY
AS1100801010002.RAW7AJ3

a nuevo nombre

AS1.txt
AS2.txt
AS3.txt
AS4.txt
AS5.txt
AS6.txt
AS7.txt
kamaruz85
fuente

Respuestas:

22

La renameherramienta que se incluye con Ubuntu es bastante atractiva en este tipo de cosas. Puede incrustar pequeñas expresiones de Perl de esta manera:

rename -n 's/.+/our $i; sprintf("AS%d.txt", 1+$i++)/e' *

Eso solo te mostrará lo que haría. Retire el -npara que sea un ejercicio de fuego vivo.

Básicamente, esto funciona definiendo de forma aproximada una variable e incrementándola cada archivo que golpeamos. Si va a tener más de 10 archivos, le sugiero que use un poco de relleno en el sprintf. Lo siguiente es bueno para 999:

rename -n 's/.+/our $i; sprintf("AS%03d.txt", 1+$i++)/e' *

... Pero eso es bastante fácil de expandir.

Oli
fuente
4

No conozco un solo comando o utilidad que haga esto, pero es bastante fácil de hacer con un bucle simple:

N=1
for X in AS*RAW*; do
  mv $X AS$N.txt
  N=$(($N+1))
done
Pablo
fuente
3

Para mejorar el @ de Oli respuesta , la renameherramienta de la versión 1.600 por Aristóteles Pagaltzis en realidad tiene un contador integrado, $N.

Entonces todo lo que necesitas es,

rename 's/AS.*/AS$N/' *

Instalar,

  1. brew install renameo descargar el script
  2. Guárdelo en un directorio en la ruta de su sistema (generalmente /usr/local/bin/brewo /usr/bin)
Atav32
fuente
3
Esta parece ser una herramienta diferente con el mismo nombre. El valor predeterminado de Ubuntu renamees el nombre previo. Esto puede ser mejor, pero es posible que desee agregar instrucciones de instalación para que esta respuesta sea más valiosa.
Oli
1
@Oli buena llamada! actualizado.
Atav32
2

renamele permite asignar directamente a $_, lo cual es ideal para este problema.

A pesar de los argumentos de código pasamos a la Perl renameutilidad realizan a menudo a juego y sustitución (con s/), y es totalmente aceptable para resolver este problema de esa manera , no hay realmente ninguna necesidad de que en casos como éste en el que no está examinando real o reutilizando el texto de los viejos nombres de archivo. renamele permite escribir casi cualquier código Perl, y no necesita ser incrustado dentro s/ /e. Sugiero usar un comando como este:

rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' *

O, si tiene ganas de afeitarse algunos caracteres:

rename -n '$_ = sprintf "AS%02d.txt", ++our$i' *

(Podría hacerse aún más corto, pero no sin sacrificar la claridad).

Ambos comandos hacen lo mismo. Cada uno muestra qué operaciones de cambio de nombre se llevarían a cabo. Una vez que pruebe uno y esté satisfecho con los resultados, ejecútelo nuevamente sin la -nopción. Como está escrito, esto produciría los nombres de archivo AS01.txt, AS02.txt, ..., AS10.txt, AS11.txt, y así sucesivamente. Puede modificarlos según sea necesario, luego solo eliminarlos -ncuando le guste lo que ve.

Si desea rellenar a un ancho mayor que 2, reemplace el 2con un número mayor. Por ejemplo, si por alguna razón quisieras nombres de archivos como AS00000000000001.txt, los reemplazarías %02dpor %014d. Si no desea ningún relleno, aunque eso haría que sus archivos aparezcan en un orden no numérico cuando los enumere más adelante, entonces puede reemplazarlos %02dpor solo %d.

¿Como funciona esto? Su shell se expande * en una lista de archivos incluso antes de ejecutar el renamecomando. La lista se ordena lexicográficamente (es decir, alfabéticamente) de acuerdo con su configuración regional actual. renamerecibe los nombres de archivo como argumentos de línea de comandos y los procesa en el orden en que se enumeran. La expresión se ++$ievalúa como uno mayor que el valor actual de la variable $i, y también establece la variable $ien ese nuevo valor incrementado. Este valor se pasa a sprintf, que lo formatea y lo coloca dentro de otro texto. Este texto se asigna directamente a la variable especial $_, que contiene el nombre del archivo. Dado que los renamearchivos de procesos en el orden en que se pasan como argumentos, se numeran en consecuencia.


¡Es posible que haya notado la similitud con la respuesta de Oli !

Ambos declaran e incrementan una variable de contador, y ambos usan sprintfesencialmente de la misma manera para incrustar el valor de ese contador, rellenado a la izquierda con ceros, en el otro texto de los nuevos nombres de archivo. (La información en cualquiera de las respuestas sobre cómo rellenar con ceros, y cambiar el ancho del relleno, incluso se aplica por igual a ambos.) La razón por la que son tan similares es que el método en esa respuesta anterior realmente está haciendo solo esto 1 , pero con pasos adicionales que son útiles para muchos problemas pero que en realidad no son necesarios para este.

A modo de comparación, así es como se ve el segundo comando en esa respuesta si se modifica para usar el estilo que he usado aquí (y para rellenar a un ancho de 2, como lo hice aquí, en lugar de 3):

rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' *

La parte entre s/.+/y /een ese comando ahora es la misma que la expresión que asigno $_(es decir, el código en el lado derecho del =operador) en el primer comando en esta respuesta.

  • El s/ operador intenta hacer coincidir el texto (nombres de archivo desde los que su shell se expandió *y pasó como argumentos de línea de comandos cuando se ejecutó rename) con una expresión regular , y realiza la sustitución. /se usa como delimitador para separar las diferentes partes de la sexpresión. La primera parte, .+es la expresión regular; coincide con cualquier carácter 1 ( .) , y lo hace una o más veces ( +) . Dado que los nombres de archivo nunca están vacíos, siempre tienen al menos un carácter de largo, esta es una forma de hacer coincidir cualquier 1 nombre de archivo.
  • Luego produce texto de cada coincidencia, es decir, de cada nombre de archivo completo, que consiste en our $i; sprintf "AS%02d.txt", ++$i. Esto produce el nuevo nombre de archivo. Por lo general, se usa s/para producir texto que (a) reemplaza el texto que coincide con solo parte del nombre de archivo, o (b) se basa de alguna manera en el texto coincidente (por ejemplo, podría usar una variable especial como la $&que se expande para el partido). En este caso, sin embargo, el texto coincidente no se está utilizando en absoluto.
  • Normalmente, el texto sustituido our $i; sprintf "AS%02d.txt", ++$ise usaría como nombre de archivo, no se ejecutaría como código. Pero la /ebandera al final hace que ese texto sea tratado como código fuente de Perl y evaluado, y usa el valor producido al hacerlo (en este caso, el valor de retorno de la función incorporada de Perl sprintf) como el nuevo nombre de archivo.

Aunque creo que el método que he mostrado aquí es un enfoque más claro y más simple para este problema que cualquier método que utiliza s/con /e, es bueno estar al tanto de que la técnica, ya que es muy adecuado para una serie de otros renombrar problemas de archivo en el que todos o parte de los nombres de archivo originales es examinado y / o retenido. Recomiendo esta publicación de blog de Oli (quien también escribió esa respuesta ), que incluye algunos ejemplos.

1 Técnicamente, no es una diferencia en el comportamiento de los $_ =comandos y los s/ /ecomandos. En la expresión regular .+, no es estrictamente cierto que .coincida con ningún carácter, porque no coincide con una nueva línea . Probablemente no deberías usar nombres de archivo con nuevas líneas en ellos, pero puedes, y ocasionalmente un archivo recibe ese nombre por accidente. Si te apetece, compara la salida de rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'la de rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar'. Para hacer .coincidir una nueva línea, use la sbandera, que va al final (con e). Es decir, escriba /seal final en lugar de /e.

Eliah Kagan
fuente
0

Suponga que los archivos que desea cambiar de nombre están en ~/Adir, y estos son los únicos archivos en esta carpeta, entonces:

n=0
for f in $( ls ~/Adir | sort ) ; do
    n=$(( n+1 ))
    mv -n "$f" "AS${n}.txt"
done

Este script examinará cada archivo ~/Adiry lo cambiará de nombre AS1.txt, AS2.txt, ...si el archivo no existe (no se sobrescribirá). Es por eso que debes asegurarte de que estos sean los únicos archivos incluidos ~/Adir. El sortcomando es solo en caso de que desee que los archivos mantengan el orden inicial.

edwin
fuente
0

Aunque el OP requiere una opción de línea de comando, también está disponible como una opción de GUI en Nautilus y es bastante fácil.

Seleccione todos los archivos requeridos y presione F2. Hay una opción llamada Números automáticos. Puede agregarlo al texto que necesita.

Sandeep C
fuente