rename
le permite asignar directamente a $_
, lo cual es ideal para este problema.
A pesar de los argumentos de código pasamos a la Perl rename
utilidad 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. rename
le 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 -n
opció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 -n
cuando le guste lo que ve.
Si desea rellenar a un ancho mayor que 2, reemplace el 2
con un número mayor. Por ejemplo, si por alguna razón quisieras nombres de archivos como AS00000000000001.txt
, los reemplazarías %02d
por %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 %02d
por solo %d
.
¿Como funciona esto? Su shell se expande *
en una lista de archivos incluso antes de ejecutar el rename
comando. La lista se ordena lexicográficamente (es decir, alfabéticamente) de acuerdo con su configuración regional actual. rename
recibe 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 ++$i
evalúa como uno mayor que el valor actual de la variable $i
, y también establece la variable $i
en 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 rename
archivos 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 sprintf
esencialmente 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 /e
en 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 s
expresió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", ++$i
se usaría como nombre de archivo, no se ejecutaría como código. Pero la /e
bandera 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/
/e
comandos. 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 s
bandera, que va al final (con e
). Es decir, escriba /se
al final en lugar de /e
.
rename
es 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.