Essas regras foram descobertas após extensos testes em uma máquina Vista. Não foram realizados testes com unicode nos nomes dos arquivos.
RENAME requer 2 parâmetros - um sourceMask, seguido por um targetMask. O sourceMask e o targetMask podem conter *
e / ou ?
curingas. O comportamento dos curingas muda ligeiramente entre as máscaras de origem e de destino.
Nota - O REN pode ser usado para renomear uma pasta, mas curingas não são permitidos no sourceMask ou no targetMask ao renomear uma pasta. Se o sourceMask corresponder a pelo menos um arquivo, os arquivos serão renomeados e as pastas serão ignoradas. Se o sourceMask corresponder apenas a pastas e não a arquivos, será gerado um erro de sintaxe se caracteres curinga aparecerem na origem ou no destino. Se o sourceMask não corresponder a nada, ocorrerá um erro "arquivo não encontrado".
Além disso, ao renomear arquivos, os curingas são permitidos apenas na parte do nome do arquivo da sourceMask. Curingas não são permitidos no caminho que leva ao nome do arquivo.
sourceMask
O sourceMask funciona como um filtro para determinar quais arquivos são renomeados. Os curingas funcionam aqui da mesma forma que com qualquer outro comando que filtra nomes de arquivos.
?
- Corresponde a qualquer caractere 0 ou 1, exceto .
Este curinga é ganancioso - ele sempre consome o próximo caractere se não for um. .
No entanto, ele não corresponderá a nada sem falhas se no final do nome ou se o próximo caractere for um.
*
- Corresponde a 0 ou mais caracteres, incluindo .
(com uma exceção abaixo). Este curinga não é ganancioso. Combina o mínimo ou o necessário para permitir a correspondência dos caracteres subseqüentes.
Todos os caracteres não curinga devem corresponder a si mesmos, com algumas exceções de caso especiais.
.
- Corresponde a si próprio ou pode corresponder ao final do nome (nada) se não houver mais caracteres. (Observação - um nome válido do Windows não pode terminar com .
)
{space}
- Corresponde a si próprio ou pode corresponder ao final do nome (nada) se não houver mais caracteres. (Observação - um nome válido do Windows não pode terminar com {space}
)
*.
no final - Corresponde a 0 ou mais caracteres, exceto .
A terminação .
pode realmente ser qualquer combinação .
e {space}
desde que o último caractere da máscara seja .
Esta é a única exceção em *
que simplesmente não corresponde a nenhum conjunto de caracteres.
As regras acima não são tão complexas. Mas há mais uma regra muito importante que torna a situação confusa: O sourceMask é comparado com o nome longo e o nome 8.3 curto (se existir). Essa última regra pode tornar a interpretação dos resultados muito complicada, porque nem sempre é óbvio quando a máscara está sendo correspondida pelo nome abreviado.
É possível usar o RegEdit para desativar a geração de nomes abreviados 8.3 em volumes NTFS, momento em que a interpretação dos resultados da máscara de arquivo é muito mais direta. Quaisquer nomes abreviados que foram gerados antes da desativação de nomes abreviados permanecerão.
targetMask
Nota - Eu não fiz nenhum teste rigoroso, mas parece que essas mesmas regras também funcionam para o nome do destino do comando COPY
O targetMask especifica o novo nome. É sempre aplicado ao nome completo completo; O targetMask nunca é aplicado ao nome abreviado 8.3, mesmo se o sourceMask corresponder ao nome abreviado 8.3.
A presença ou ausência de curingas no sourceMask não tem impacto sobre como os curingas são processados no targetMask.
Na discussão a seguir - c
representa qualquer caractere que não é *
, ?
ou.
O targetMask é processado com relação ao nome da fonte estritamente da esquerda para a direita, sem rastreamento de retorno.
c
- Avança a posição dentro do nome da fonte, desde que o próximo caractere não seja .
e anexa c
ao nome do destino. (Substitui o caractere que estava na fonte por c
, mas nunca substitui .
)
?
- Corresponde ao próximo caractere do nome longo da fonte e o anexa ao nome do destino, desde que o próximo caractere não seja. .
Se o próximo caractere estiver .
ou se estiver no final do nome da fonte, nenhum caractere será adicionado ao resultado e ao atual. A posição no nome da fonte permanece inalterada.
*
no final de targetMask - anexa todos os caracteres restantes da origem ao destino. Se já estiver no final da fonte, não fará nada.
*c
- Corresponde a todos os caracteres de origem da posição atual até a última ocorrência de c
(correspondência gananciosa com distinção entre maiúsculas e minúsculas) e anexa o conjunto de caracteres correspondente ao nome do destino. Se c
não for encontrado, todos os caracteres restantes da origem serão anexados, seguidos por c
Esta é a única situação em que sei onde a correspondência de padrões de arquivo do Windows faz distinção entre maiúsculas e minúsculas.
*.
- Corresponde a todos os caracteres de origem da posição atual até a última ocorrência de .
(correspondência gananciosa) e anexa o conjunto de caracteres correspondente ao nome do destino. Se .
não for encontrado, todos os caracteres restantes da fonte serão anexados, seguidos por.
*?
- Anexa todos os caracteres restantes da origem ao destino. Se já estiver no final da fonte, não fará nada.
.
sem *
na frente - Avança a posição na origem pela primeira vez em .
sem copiar nenhum caractere e anexa .
ao nome do destino. Se .
não for encontrado na fonte, avança para o final da fonte e anexa .
ao nome do destino.
Após a targetMask foi esgotado, qualquer fuga .
e {space}
são aparadas off no final do nome do alvo resultante porque nomes de arquivos do Windows não pode terminar com .
ou{space}
Alguns exemplos práticos
Substitua um caractere na 1ª e na 3ª posições antes de qualquer extensão (adiciona um 2º ou 3º caractere se ele ainda não existir)
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
Alterar a extensão (final) de cada arquivo
ren * *.txt
a -> a.txt
b.dat -> b.txt
c.x.y -> c.x.txt
Anexar uma extensão a cada arquivo
ren * *?.bak
a -> a.bak
b.dat -> b.dat.bak
c.x.y -> c.x.y.bak
Remova qualquer extensão extra após a extensão inicial. Observe que adequado ?
deve ser usado para preservar o nome completo existente e a extensão 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)
O mesmo que acima, mas filtre os arquivos com nome e / ou extensão inicial com mais de 5 caracteres, para que não sejam truncados. (Obviamente, pode adicionar um adicional ?
em cada extremidade do targetMask para preservar nomes e extensões com até 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)
Altere os caracteres após o último _
no nome e tente preservar a extensão. (Não funciona corretamente se _
aparecer na extensão)
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)
Qualquer nome pode ser dividido em componentes que são delimitados por .
caracteres, que podem ser anexados ou excluídos apenas no final de cada componente. Os caracteres não podem ser excluídos ou adicionados ao início ou no meio de um componente, preservando o restante com caracteres curinga. Substituições são permitidas em qualquer 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
Se os nomes abreviados estiverem ativados, uma sourceMask com pelo menos 8 ?
para o nome e pelo menos 3 ?
para a extensão corresponderá a todos os arquivos, pois sempre corresponderá ao nome 8.3 abreviado.
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
Peculiar / bug útil? para excluir prefixos de nome
Esta postagem do Superusuário descreve como um conjunto de barras ( /
) pode ser usado para excluir caracteres iniciais de um nome de arquivo. Uma barra é necessária para cada caractere a ser excluído. Confirmei o comportamento em uma máquina Windows 10.
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
Essa técnica funciona apenas se as máscaras de origem e de destino estiverem entre aspas duplas. Todos os seguintes formulários sem as cotações necessárias falham com este erro: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
Não /
pode ser usado para remover nenhum caractere no meio ou no final de um nome de arquivo. Só pode remover caracteres iniciais (prefixo).
Tecnicamente, o /
não está funcionando como um curinga. Em vez disso, ele está fazendo uma substituição simples de caracteres, mas, após a substituição, o comando REN reconhece que /
não é válido em um nome de arquivo e retira as /
barras principais do nome. O REN gera um erro de sintaxe se detectar /
no meio do nome de um destino.
Possível bug RENAME - um único comando pode renomear o mesmo arquivo duas vezes!
Iniciando em uma pasta de teste vazia:
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
Acredito que o sourceMask *1*
corresponda primeiro ao nome do arquivo longo, e o arquivo é renomeado para o resultado esperado de 223456789.123.x
. RENAME continua a procurar mais arquivos para processar e localiza o novo arquivo nomeado por meio do novo nome abreviado de 223456~1.X
. O arquivo é renomeado novamente, fornecendo o resultado final de 223456789.123.xx
.
Se eu desativar a geração de nomes 8.3, o RENAME fornecerá o resultado esperado.
Ainda não elaborei completamente todas as condições de gatilho que devem existir para induzir esse comportamento estranho. Eu estava preocupado que fosse possível criar um RENAME recursivo sem fim, mas nunca consegui induzi-lo.
Acredito que todos os itens a seguir devem ser verdadeiros para induzir o bug. Cada caso com bug que eu vi tinha as seguintes condições, mas nem todos os casos que atendiam às seguintes condições eram com bug.
- Nomes curtos 8.3 devem estar ativados
- O sourceMask deve corresponder ao nome longo original.
- A renomeação inicial deve gerar um nome abreviado que também corresponda ao sourceMask
- O nome abreviado renomeado inicial deve classificar depois do nome abreviado original (se existir?)