Como o comando RENAME (REN) do Windows interpreta caracteres curinga?
O recurso de ajuda incorporado não ajuda em nada - ele não trata de curingas.
A ajuda online do Microsoft technet XP não é muito melhor. Aqui está tudo o que tem a dizer sobre caracteres curinga:
"Você pode usar caracteres curinga (
*
e?
) em qualquer parâmetro de nome de arquivo. Se você usar caracteres curinga no nome do arquivo2, os caracteres representados pelos caracteres curinga serão idênticos aos caracteres correspondentes no nome do arquivo1."
Não há muita ajuda - há muitas maneiras pelas quais essa declaração pode ser interpretada.
Consegui usar com sucesso caracteres curinga no parâmetro filename2 em algumas ocasiões, mas sempre foi tentativa e erro. Não pude prever o que funciona e o que não funciona. Freqüentemente, tive que recorrer a escrever um pequeno script em lote com um loop FOR que analisa cada nome para que eu possa criar cada novo nome conforme necessário. Não é muito conveniente.
Se eu soubesse as regras de como os curingas são processados, acho que poderia usar o comando RENAME com mais eficiência sem precisar recorrer ao lote com a mesma frequência. É claro que conhecer as regras também beneficiaria o desenvolvimento de lotes.
(Sim - este é um caso em que estou postando uma pergunta e resposta emparelhadas. Me cansei de não conhecer as regras e decidi experimentar por conta própria. Acho que muitos outros podem estar interessados no que descobri)
fonte
*
, o Windows permite. Isso tem enormes consequências. Eu gostaria de saber sobre esse site; isso poderia ter facilitado minha investigação. As regras do MSDOS7 são significativamente diferentes das regras antigas do DOS, antes de nomes de arquivos longos, e são um passo na direção de como o Windows lida com isso. Eu havia encontrado as regras do DOS de nome de arquivo longo e não valiam a pena investigar.Respostas:
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 anexac
ao nome do destino. (Substitui o caractere que estava na fonte porc
, 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 dec
(correspondência gananciosa com distinção entre maiúsculas e minúsculas) e anexa o conjunto de caracteres correspondente ao nome do destino. Sec
não for encontrado, todos os caracteres restantes da origem serão anexados, seguidos porc
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)
Alterar a extensão (final) de cada arquivo
Anexar uma extensão a cada arquivo
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.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)Altere os caracteres após o último
_
no nome e tente preservar a extensão. (Não funciona corretamente se_
aparecer na extensão)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.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.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.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
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:
Acredito que o sourceMask
*1*
corresponda primeiro ao nome do arquivo longo, e o arquivo é renomeado para o resultado esperado de223456789.123.x
. RENAME continua a procurar mais arquivos para processar e localiza o novo arquivo nomeado por meio do novo nome abreviado de223456~1.X
. O arquivo é renomeado novamente, fornecendo o resultado final de223456789.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.
fonte
REN /?
.Copy of
prefixo usando uma técnica barra obscuro:ren "Copy of *.txt" "////////*"
Semelhante ao exebook, aqui está uma implementação em C # para obter o nome do arquivo de destino de um arquivo de origem.
Encontrei 1 pequeno erro nos exemplos de dbenham:
Aqui está o código:
E aqui está um método de teste NUnit para testar os exemplos:
fonte
Eu consegui escrever esse código no BASIC para mascarar nomes de arquivos curinga:
fonte
Talvez alguém possa achar isso útil. Este código JavaScript é baseado na resposta de dbenham acima.
Não testei
sourceMask
muito, mastargetMask
corresponde a todos os exemplos dados por dbenham.fonte