Estas regras foram descobertas após extensos testes numa máquina Vista. Nenhum teste foi feito com unicode em nomes de ficheiro.
RENAME requer 2 parâmetros - uma máscara de origem, seguida por uma máscara de destino. Tanto a sourceMask como a targetMask podem conter *
e/ou ?
wildcards. O comportamento dos wildcards muda ligeiramente entre as máscaras-fonte e as máscaras-alvo.
Nota - REN pode ser utilizada para renomear uma pasta, mas os wildcards são não* permitidos na MáscaraFonte ou na Máscara de destino quando se renomeia uma pasta. Se a sourceMask corresponder a pelo menos um ficheiro, então o(s) ficheiro(s) será(ão) renomeado(s) e as pastas serão ignoradas. Se a MáscaraFonte corresponder apenas a pastas e não a ficheiros, então será gerado um erro de sintaxe se aparecerem wildcards na fonte ou no alvo. Se a MáscaraFonte não corresponder a nada, então resulta um erro “ficheiro não encontrado”.
Também, ao renomear ficheiros, os wildcards só são permitidos na parte do nome do ficheiro da MáscaraFonte. Os wildcards não são permitidos no caminho que conduz ao nome do ficheiro.
sourceMask
A sourceMask funciona como um filtro para determinar que ficheiros são renomeados. Os wildcards funcionam aqui como com qualquer outro comando que filtra os nomes dos ficheiros.
?
- Corresponde a qualquer 0 ou 1 caracter exceto .
Este wildcard é ganancioso - consome sempre o próximo caracter se não for um .
No entanto, não corresponde a nada sem falha se no fim do nome ou se o próximo caractere for um .
*
- Corresponde a qualquer 0 ou mais caracteres incluindo .
(com uma excepção abaixo). Este wildcard não é ganancioso. Combina tão pouco ou tanto quanto for necessário para permitir a correspondência de caracteres subsequentes.
Todos os caracteres que não sejam wildcard devem corresponder a si mesmos, com algumas excepções de casos especiais.
.
- Corresponde a si próprio ou pode corresponder ao fim do nome (nada) se não restarem mais caracteres. (Nota - um nome válido do Windows não pode terminar com .
)
{space}
* - Corresponde a si próprio ou pode corresponder ao fim do nome (nada), se não restarem mais caracteres. (Nota - um nome válido do Windows não pode terminar com {space}
)
*.
* no fim - Combina qualquer 0 ou mais caracteres exceto .
A terminação .
pode realmente ser qualquer combinação de .
e {space}
desde que o último caractere na máscara seja .
Esta é a única e única excepção onde *
não combina simplesmente com qualquer conjunto de caracteres.
As regras acima não são assim tão complexas. Mas há mais uma regra muito importante que torna a situação confusa: A sourceMask é comparada tanto com o nome longo como com o nome curto 8.3 (se existir). Esta última regra pode tornar a interpretação dos resultados muito complicada, porque nem sempre é óbvia quando a máscara é comparada através do nome curto.
É possível utilizar RegEdit para desactivar a geração de nomes curtos de 8,3 nomes em volumes NTFS, altura em que a interpretação dos resultados da máscara de arquivo é muito mais directa. Qualquer nome curto que tenha sido gerado antes de desactivar nomes curtos permanecerá.
targetMask
Note - Não fiz nenhum teste rigoroso, mas parece que estas mesmas regras também funcionam para o nome alvo do comando COPY
A targetMask especifica o novo nome. É sempre aplicada ao nome longo completo; A targetMask nunca é aplicada ao nome curto 8.3, mesmo que a sourceMask corresponda ao nome curto 8.3.
A presença ou ausência de wildcards na máscara de origem não tem impacto na forma como os wildcards são processados na Máscara de destino.
Na discussão seguinte - c
representa qualquer carácter que não seja *
, ?
, ou .
A Máscara da fonte é processada contra o nome da fonte estritamente da esquerda para a direita, sem retrocesso.
c
- Avança a posição dentro do nome da fonte apenas se o carácter da fonte não for .
, e acrescenta sempre c
ao nome do alvo. (Substitui o caractere que estava na fonte por c
, mas nunca substitui .
)
?
* - Faz corresponder o próximo caractere do nome longo da fonte e anexa-o ao nome alvo desde que o caractere da fonte não seja .
Se o próximo caractere for .
ou se no fim do nome da fonte, então nenhum caractere é adicionado ao resultado e a posição actual dentro do nome da fonte é inalterada.
*
no fim da Máscara de destino - Acrescenta todos os caracteres restantes da fonte ao alvo. Se já estiver no fim da fonte, então não faz nada.
& - *c
* - Junta todos os caracteres da posição actual até à última ocorrência de c
& (correspondência gananciosa sensível a maiúsculas e minúsculas) e anexa o conjunto de caracteres correspondentes ao nome do alvo. Se c
não for encontrado, então todos os caracteres restantes da fonte são anexados, seguidos de c
Esta é a única situação que conheço em que a correspondência de padrão de ficheiro do Windows é sensível a maiúsculas e minúsculas.
*.
- Combina todos os caracteres da posição actual através da última ocasião de .
(correspondência gananciosa) e anexa o conjunto combinado de caracteres para o nome do alvo. Se .
não for encontrado, então todos os caracteres restantes da fonte são anexados, seguidos de .
*?
* - anexa todos os caracteres restantes da fonte ao alvo. Se já estiver no fim da fonte, então nada faz.
.
* sem *
na frente - Avança a posição na fonte através da primeira ocorrência de .
sem copiar quaisquer caracteres, e anexa .
ao nome do alvo. Se .
não for encontrado na fonte, então avança para o fim da fonte e anexa .
ao nome do alvo.
após a Máscara alvo ter sido esgotada, Qualquer trailing .
e {space}
são aparados no final do nome do alvo resultante porque os nomes dos ficheiros Windows não podem terminar com .
ou {space}
Alguns exemplos práticos
Substituir um caractere na 1ª e 3ª posições antes de qualquer extensão (adiciona um 2º ou 3º caracter se 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 ficheiro
ren * *.txt
a -> a.txt
b.dat -> b.txt
c.x.y -> c.x.txt
Anexar uma extensão a cada ficheiro
ren * *?.bak
a -> a.bak
b.dat -> b.dat.bak
c.x.y -> c.x.y.bak
Remover qualquer extensão extra após a extensão inicial. Note-se 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 filtrar os ficheiros com nome inicial e/ou extensão superior a 5 caracteres, para que não sejam truncados. (Obviamente poderia adicionar um ?
adicional em cada extremidade da targetMask para preservar nomes e extensões 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)
Alterar caracteres após a última _
no nome e tentar preservar a extensão. (Não funciona correctamente 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 .
Os caracteres só podem ser anexados ou eliminados do final de cada componente. Os caracteres não podem ser apagados ou adicionados ao início ou meio de um componente, preservando o resto com wildcards. As 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 curtos estiverem activados, então uma Máscara Fonte com pelo menos 8 ?
para o nome e pelo menos 3 ?
para a extensão irá corresponder a todos os ficheiros porque irá sempre corresponder ao nome curto 8,3.
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
Quirk/bug? útil para apagar prefixos de nomes
Este post SuperUser descreve como um conjunto de barras de avanço (/
) pode ser usado para apagar caracteres principais de um nome de ficheiro. É necessária uma barra para cada caracter a ser eliminado. Confirmei o comportamento numa máquina Windows 10.
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
Esta técnica só funciona se tanto a máscara de origem como a de destino estiverem entre aspas duplas. Todas as seguintes formas sem as aspas 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
A /
não pode ser utilizada para remover quaisquer caracteres no meio ou no fim de um nome de ficheiro. Só pode remover os caracteres principais (prefixo). Note-se também que esta técnica não funciona com nomes de pastas.
Tecnicamente o /
não funciona como um wildcard. Em vez disso, está a fazer uma simples substituição de caracteres, mas depois da substituição, o comando REN reconhece que /
não é válido num nome de ficheiro, e retira o /
inicial do nome. REN dá um erro de sintaxe se detectar /
no meio de um nome de destino.
Possível erro RENAME - um único comando pode renomear o mesmo ficheiro duas vezes!
Começando numa 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 a Máscara Fonte *1*
corresponde primeiro ao nome longo do ficheiro, e o ficheiro é renomeado para o resultado esperado de 223456789.123.x
. RENAME continua então a procurar mais ficheiros para processar e encontra o ficheiro recentemente nomeado através do novo nome curto de 223456~1.X
. O ficheiro é então renomeado de novo, dando o resultado final de 223456789.123.xx
.
Se eu desactivar a geração de 8,3 nomes, então a RENAME dá o resultado esperado.
Ainda não resolvi todas as condições de desencadeamento que devem existir para induzir este comportamento estranho. Estava preocupado com a possibilidade de ser possível criar um RENAME recorrente sem fim, mas nunca fui capaz de induzir um.
Creio que tudo o que se segue deve ser verdade para induzir o insecto. Todos os casos que eu vi tinham as seguintes condições, mas nem todos os casos que preenchiam as seguintes condições tinham sido submetidos a uma escuta.
- Os nomes curtos 8,3 devem ser activados
- A máscara de origem deve corresponder ao nome longo original.
& - A renomeação inicial tem de gerar um nome curto que também coincida com o nome curto original da Máscara Fonte
- A renomeação inicial tem de ser ordenada mais tarde do que o nome curto original (se existisse?)