Estas reglas fueron descubiertas después de extensas pruebas en una máquina Vista. No se hicieron pruebas con unicode en los nombres de archivo._
RENAME requiere 2 parámetros - un sourceMask, seguido de un targetMask. Tanto la sourceMask como la targetMask pueden contener comodines *
y/o ?
. El comportamiento de los comodines cambia ligeramente entre las máscaras de origen y de destino.
Nota - REN puede usarse para renombrar una carpeta, pero los comodines no están permitidos ni en la sourceMask ni en la targetMask al renombrar una carpeta. Si la sourceMask coincide con al menos un archivo, se renombrarán los archivos y se ignorarán las carpetas. Si la sourceMask sólo coincide con carpetas y no con archivos, se generará un error de sintaxis si aparecen comodines en el origen o en el destino. Si el sourceMask no coincide con nada, entonces se genera un error de “archivo no encontrado”.
Además, al renombrar archivos, los comodines sólo se permiten en la parte del nombre del archivo del sourceMask. Los comodines no están permitidos en la ruta que lleva al nombre del archivo.
sourceMask
El sourceMask funciona como un filtro para determinar qué archivos se renombran. Los comodines funcionan aquí igual que con cualquier otro comando que filtre nombres de archivos.
?
- Coincide con cualquier carácter 0 o 1 excepto .
Este comodín es codicioso - siempre consume el siguiente carácter si no es un .
Sin embargo no coincidirá con nada sin fallo si al final del nombre o si el siguiente carácter es un .
*
- Coincide con cualquier carácter 0 o más incluyendo .
(con una excepción más abajo). Este comodín no es codicioso. Coincidirá con lo poco o mucho que sea necesario para permitir que los caracteres subsiguientes coincidan.
Todos los caracteres que no son comodines deben coincidir por sí mismos, con algunas excepciones de casos especiales.
.
- Coincide consigo mismo o puede coincidir con el final del nombre (nada) si no quedan más caracteres. (Nota - un nombre válido de Windows no puede terminar con .
)
{space}
- Coincide consigo mismo o puede coincidir con el final del nombre (nada) si no quedan más caracteres. (Nota - un nombre válido de Windows no puede terminar con {space}
)
*.
al final - Coincide con cualquier 0 o más caracteres excepto .
El .
final puede ser en realidad cualquier combinación de .
y {space}
siempre que el último carácter de la máscara sea .
Esta es la única excepción en la que *
no coincide simplemente con cualquier conjunto de caracteres.
Las reglas anteriores no son tan complejas. Pero hay otra regla muy importante que hace que la situación sea confusa: El sourceMask se compara tanto con el nombre largo como con el nombre corto 8.3 (si existe). Esta última regla puede hacer que la interpretación de los resultados sea muy complicada, ya que no siempre es obvio cuando la máscara coincide con el nombre corto.
Es posible utilizar RegEdit para desactivar la generación de nombres cortos 8.3 en los volúmenes NTFS, en cuyo caso la interpretación de los resultados de la máscara de archivo es mucho más sencilla. Cualquier nombre corto que se haya generado antes de deshabilitar los nombres cortos se mantendrá.
targetMask
Nota - No he hecho ninguna prueba rigurosa, pero parece que estas mismas reglas también funcionan para el nombre de destino del comando COPY
El targetMask especifica el nuevo nombre. Siempre se aplica al nombre largo completo; La targetMask nunca se aplica al nombre corto 8.3, incluso si la sourceMask coincidió con el nombre corto 8.3.
La presencia o ausencia de comodines en la sourceMask no tiene ningún impacto en cómo se procesan los comodines en la targetMask.
En la siguiente discusión - c
representa cualquier carácter que no sea *
, ?
, o .
La targetMask se procesa contra el nombre fuente estrictamente de izquierda a derecha sin retroceso.
c
- Avanza la posición dentro del nombre de origen sólo si el carácter de origen no es .
, y siempre añade c
al nombre de destino. (Reemplaza el carácter que estaba en el origen con c
, pero nunca reemplaza a .
)
?
- Coincide con el siguiente carácter del nombre largo de origen y lo añade al nombre de destino siempre que el carácter de origen no sea .
Si el siguiente carácter es .
o si está al final del nombre de origen entonces no se añade ningún carácter al resultado y la posición actual dentro del nombre de origen no cambia.
*
al final de targetMask - Añade todos los caracteres restantes del origen al destino. Si ya está al final de la fuente, no hace nada.
*c
- Busca todos los caracteres del origen desde la posición actual hasta la última ocurrencia de c
(coincidencia codiciosa sensible a mayúsculas y minúsculas) y añade el conjunto de caracteres coincidentes al nombre de destino. Si no se encuentra c
, entonces se añaden todos los caracteres restantes del origen, seguidos de c
Esta es la única situación que conozco en la que la coincidencia de patrones de archivos de Windows distingue entre mayúsculas y minúsculas.
*.
- Coincide con todos los caracteres del origen desde la posición actual hasta la última aparición de .
(coincidencia codiciosa) y añade el conjunto de al nombre de destino. Si no se encuentra .
, se añaden todos los caracteres restantes del origen, seguidos de .
*?
- Añade todos los caracteres restantes del origen al destino. Si ya está al final del origen, no hace nada.
.
sin *
delante - Avanza la posición en el origen hasta la primera aparición de .
sin copiar ningún carácter, y añade .
al nombre de destino. Si .
no se encuentra en el origen, entonces avanza hasta el final del origen y añade .
al nombre de destino.
Una vez agotada la targetMask, cualquier .
y {space}
al final del nombre de destino resultante porque los nombres de archivo de Windows no pueden terminar con .
o {space}
Algunos ejemplos prácticos
Sustituye un carácter en la 1ª y 3ª posición antes de cualquier extensión (añade un 2º o 3º carácter si aún no existe)
ren * A?Z*
1 -> AZ
12 -> A2Z
1.txt -> AZ.txt
12.txt -> A2Z.txt
123 -> A2Z
123.txt -> A2Z.txt
1234 -> A2Z4
1234.txt -> A2Z4.txt
Cambia la extensión (final) de cada archivo
ren * *.txt
a -> a.txt
b.dat -> b.txt
c.x.y -> c.x.txt
Añade una extensión a cada archivo
ren * *?.bak
a -> a.bak
b.dat -> b.dat.bak
c.x.y -> c.x.y.bak
Elimina cualquier extensión extra después de la inicial. Tenga en cuenta que el ?
adecuado debe utilizarse para conservar el nombre completo existente y la extensión inicial.
ren * ?????.?????
a -> a
a.b -> a.b
a.b.c -> a.b
part1.part2.part3 -> part1.part2
123456.123456.123456 -> 12345.12345 (note truncated name and extension because not enough `?` were used)
Igual que el anterior, pero filtrando los archivos con nombre inicial y/o extensión de más de 5 caracteres para que no se trunquen. (Obviamente, podría añadir un ?
adicional en cada extremo de targetMask para preservar nombres y extensiones de hasta 6 caracteres)
ren ?????.?????.* ?????.?????
a -> a
a.b -> a.b
a.b.c -> a.b
part1.part2.part3 -> part1.part2
123456.123456.123456 (Not renamed because doesn't match sourceMask)
Cambia los caracteres después del último _
en el nombre e intenta preservar la extensión. (No funciona correctamente si el _
aparece en la extensión)
ren *_* *_NEW.*
abcd_12345.txt -> abcd_NEW.txt
abc_newt_1.dat -> abc_newt_NEW.dat
abcdef.jpg (Not renamed because doesn't match sourceMask)
abcd_123.a_b -> abcd_123.a_NEW (not desired, but no simple RENAME form will work in this case)
Cualquier nombre puede dividirse en componentes delimitados por .
Los caracteres sólo pueden añadirse o eliminarse del final de cada componente. No se pueden eliminar o añadir caracteres al principio o a la mitad de un componente conservando el resto con comodines. Las sustituciones están permitidas en cualquier lugar.
ren ??????.??????.?????? ?x.????999.*rForTheCourse
part1.part2 -> px.part999.rForTheCourse
part1.part2.part3 -> px.part999.parForTheCourse
part1.part2.part3.part4 (Not renamed because doesn't match sourceMask)
a.b.c -> ax.b999.crForTheCourse
a.b.CarPart3BEER -> ax.b999.CarParForTheCourse
Si los nombres cortos están habilitados, entonces una sourceMask con al menos 8 ?
para el nombre y al menos 3 ?
para la extensión coincidirá con todos los archivos porque siempre coincidirá con el nombre corto 8.3.
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
¿Una peculiaridad/bug? para borrar los prefijos de los nombres
Este post de SuperUser describe cómo se puede utilizar un conjunto de barras inclinadas (/
) para borrar los caracteres iniciales de un nombre de archivo. Se requiere una barra por cada carácter a eliminar. He confirmado el comportamiento en una máquina Windows 10.
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
Esta técnica sólo funciona si tanto la máscara de origen como la de destino están entre comillas dobles. Todas las formas siguientes sin las comillas requeridas fallan con este error: The syntax of the command is incorrect
REM - All of these forms fail with a syntax error.
ren abc-*.txt "////*.txt"
ren "abc-*.txt" ////*.txt
ren abc-*.txt ////*.txt
El /
no puede utilizarse para eliminar ningún carácter en el medio o al final de un nombre de archivo. Sólo puede eliminar los caracteres iniciales (prefijos). Tenga en cuenta también que esta técnica no funciona con los nombres de las carpetas.
Técnicamente el /
no funciona como un comodín. Más bien está haciendo una simple sustitución de caracteres, pero después de la sustitución, el comando REN reconoce que /
no es válido en un nombre de archivo, y elimina las barras iniciales /
del nombre. REN da un error de sintaxis si detecta /
en medio de un nombre de destino.
Posible error de RENAME - ¡un solo comando puede renombrar el mismo archivo dos veces!
Comenzando en una carpeta de prueba vacía:
C:\test>copy nul 123456789.123
1 file(s) copied.
C:\test>dir /x
Volume in drive C is OS
Volume Serial Number is EE2C-5A11
Directory of C:\test
09/15/2012 07:42 PM <DIR> .
09/15/2012 07:42 PM <DIR> ..
09/15/2012 07:42 PM 0 123456~1.123 123456789.123
1 File(s) 0 bytes
2 Dir(s) 327,237,562,368 bytes free
C:\test>ren *1* 2*3.?x
C:\test>dir /x
Volume in drive C is OS
Volume Serial Number is EE2C-5A11
Directory of C:\test
09/15/2012 07:42 PM <DIR> .
09/15/2012 07:42 PM <DIR> ..
09/15/2012 07:42 PM 0 223456~1.XX 223456789.123.xx
1 File(s) 0 bytes
2 Dir(s) 327,237,562,368 bytes free
REM Expected result = 223456789.123.x
Creo que el sourceMask *1*
primero coincide con el nombre largo del archivo, y el archivo es renombrado al resultado esperado de 223456789.123.x
. RENAME entonces continúa buscando más archivos para procesar y encuentra el archivo recién nombrado a través del nuevo nombre corto de 223456~1.X
. El archivo es renombrado de nuevo dando el resultado final de 223456789.123.xx
.
Si desactivo la generación de nombres de 8.3 entonces el RENAME da el resultado esperado.
Aún no he podido averiguar todas las condiciones de activación que deben existir para inducir este extraño comportamiento. Me preocupaba que fuera posible crear un RENAME recursivo interminable, pero nunca pude inducirlo.
Creo que todo lo siguiente debe ser cierto para inducir el error. Todos los casos con fallos que vi tenían las siguientes condiciones, pero no todos los casos que cumplían las siguientes condiciones tenían fallos.
- Los nombres cortos 8.3 deben estar habilitados
- La sourceMask debe coincidir con el nombre largo original.
- El renombrado inicial debe generar un nombre corto que también coincida con el sourceMask
- El nombre corto inicial renombrado debe ser posterior al nombre corto original (si es que existía)