Queste regole sono state scoperte dopo lunghi test su una macchina Vista. Nessun test è stato fatto con unicode nei nomi dei file._
RENAME richiede 2 parametri - una sourceMask, seguita da una targetMask. Sia la sourceMask che la targetMask possono contenere caratteri jolly *
e/o ?
. Il comportamento dei caratteri jolly cambia leggermente tra le maschere di origine e di destinazione.
Note - REN può essere usato per rinominare una cartella, ma i caratteri jolly non sono non ammessi né nella sourceMask né nella targetMask quando si rinomina una cartella. Se la sourceMask corrisponde ad almeno un file, allora il file o i file saranno rinominati e le cartelle saranno ignorate. Se la sourceMask corrisponde solo alle cartelle e non ai file, allora viene generato un errore di sintassi se i caratteri jolly appaiono in source o target. Se la sourceMask non corrisponde a nulla, allora viene generato un errore “file not found”.
Inoltre, quando si rinominano i file, i caratteri jolly sono ammessi solo nella porzione del nome del file della sourceMask. I caratteri jolly non sono ammessi nel percorso che porta al nome del file.
sourceMask
La sourceMask funziona come un filtro per determinare quali file vengono rinominati. I caratteri jolly funzionano qui come con qualsiasi altro comando che filtra i nomi dei file.
?
- Corrisponde a qualsiasi carattere 0 o 1 eccetto .
Questo carattere jolly è avido - consuma sempre il carattere successivo se non è uno .
Tuttavia non corrisponderà a nulla senza fallire se alla fine del nome o se il carattere successivo è uno .
*
- Corrisponde a qualsiasi carattere 0 o più incluso .
(con un'eccezione sotto). Questo carattere jolly non è avido. Corrisponderà tanto o poco quanto è necessario per permettere ai caratteri successivi di corrispondere.
Tutti i caratteri non jolly devono corrispondere a se stessi, con alcune eccezioni di casi speciali.
.
- Corrisponde a se stesso o può corrispondere alla fine del nome (niente) se non rimangono altri caratteri. (Nota - un nome Windows valido non può finire con .
)
{space}
- Corrisponde a se stesso o può corrispondere alla fine del nome (niente) se non rimangono altri caratteri. (Nota - un nome Windows valido non può finire con {space}
)
*.
alla fine - Corrisponde a qualsiasi 0 o più caratteri eccetto .
Lo .
terminante può essere in realtà qualsiasi combinazione di .
e {space}
finché l'ultimo carattere della maschera è .
Questa è la sola e unica eccezione dove *
non corrisponde semplicemente a qualsiasi serie di caratteri.
Le regole di cui sopra non sono così complesse. Ma c'è un'altra regola molto importante che rende la situazione confusa: La sourceMask viene confrontata sia con il nome lungo che con il nome corto 8.3 (se esiste). Quest'ultima regola può rendere l'interpretazione dei risultati molto complicata, perché non è sempre ovvio quando la maschera viene confrontata con il nome corto.
È possibile usare RegEdit per disabilitare la generazione di nomi brevi 8.3 sui volumi NTFS, a questo punto l'interpretazione dei risultati della maschera di file è molto più semplice. Qualsiasi nome breve generato prima di disabilitare i nomi brevi rimarrà.
targetMask
Nota - Non ho fatto alcun test rigoroso, ma sembra che queste stesse regole funzionino anche per il nome di destinazione del comando COPY
La targetMask specifica il nuovo nome. Viene sempre applicata al nome lungo completo; la targetMask non viene mai applicata al nome corto 8.3, anche se la sourceMask corrispondeva al nome corto 8.3.
La presenza o l'assenza di caratteri jolly nella sourceMask non ha alcun impatto su come i caratteri jolly vengono elaborati nella targetMask.
Nella seguente discussione - c
rappresenta qualsiasi carattere che non sia *
, ?
, o .
La targetMask è processata rispetto al nome sorgente rigorosamente da sinistra a destra senza back-tracking.
c
- Fa avanzare la posizione all'interno del nome sorgente solo se il carattere sorgente non è .
, e aggiunge sempre c
al nome target. (Sostituisce il carattere che era nel sorgente con c
, ma non sostituisce mai .
)
?
- Corrisponde al prossimo carattere del nome lungo sorgente e lo aggiunge al nome di destinazione finché il carattere sorgente non è .
Se il prossimo carattere è .
o se è alla fine del nome sorgente allora nessun carattere viene aggiunto al risultato e la posizione corrente all'interno del nome sorgente è invariata.
*
alla fine di targetMask - Aggiunge tutti i caratteri rimanenti dal sorgente al target. Se è già alla fine del sorgente, allora non fa nulla.
*c
- Corrisponde a tutti i caratteri dell'origine dalla posizione corrente fino all'ultima occorrenza di c
(corrispondenza sensibile alle maiuscole e alle minuscole) e aggiunge l'insieme dei caratteri corrispondenti al nome di destinazione. Se c
non viene trovato, allora tutti i caratteri rimanenti dal sorgente vengono aggiunti, seguiti da c
Questa è l'unica situazione di cui sono a conoscenza in cui la corrispondenza del pattern di file di Windows è sensibile alle maiuscole.
*.
- Corrisponde a tutti i caratteri del sorgente dalla posizione corrente fino all’ultima occorrenza di .
(greedy match) e aggiunge l'insieme di al nome di destinazione. Se .
non viene trovato, allora vengono aggiunti tutti i caratteri rimanenti dal sorgente, seguiti da .
*?
- Aggiunge tutti i caratteri rimanenti dal sorgente alla destinazione. Se è già alla fine del sorgente allora non fa nulla.
.
senza *
davanti - Avanza la posizione nel sorgente fino alla prima occorrenza di .
senza copiare alcun carattere, e aggiunge .
al nome di destinazione. Se .
non si trova nel sorgente, allora avanza fino alla fine del sorgente e aggiunge .
al nome di destinazione.
Dopo che la targetMask è stata esaurita, qualsiasi traccia di .
e {space}
viene tagliata dalla fine del nome di destinazione risultante, perché i nomi di file Windows non possono finire con .
o {space}
Alcuni esempi pratici
Sostituisci un carattere nella 1a e 3a posizione prima di qualsiasi estensione (aggiunge un 2° o 3° carattere se non esiste ancora)
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
Cambiare l'estensione (finale) di ogni file
ren * *.txt
a -> a.txt
b.dat -> b.txt
c.x.y -> c.x.txt
Aggiungere un'estensione ad ogni file
ren * *?.bak
a -> a.bak
b.dat -> b.dat.bak
c.x.y -> c.x.y.bak
Rimuovere qualsiasi estensione extra dopo l'estensione iniziale. Nota che ?
adeguato deve essere usato per preservare il nome completo esistente e l'estensione iniziale.
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)
Come sopra, ma filtra i file con nome iniziale e/o estensione più lunghi di 5 caratteri in modo che non vengano troncati. (Ovviamente si potrebbe aggiungere un ulteriore ?
alle due estremità di targetMask per preservare nomi ed estensioni fino a 6 caratteri)
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 i caratteri dopo l'ultimo _
nel nome e cerca di preservare l'estensione. (Non funziona correttamente se _
appare nell'estensione)
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)
Qualsiasi nome può essere suddiviso in componenti che sono delimitati da .
I caratteri possono essere solo aggiunti o cancellati dalla fine di ogni componente. I caratteri non possono essere cancellati o aggiunti all'inizio o al centro di un componente conservando il resto con i caratteri jolly. Le sostituzioni sono permesse ovunque.
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 i nomi brevi sono abilitati, allora una sourceMask con almeno 8 ?
per il nome e almeno 3 ?
per l'estensione corrisponderà a tutti i file perché corrisponderà sempre al nome breve 8.3.
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
Utile stranezza/bug? per cancellare i prefissi dei nomi
Questo post del SuperUser descrive come una serie di slash (/
) può essere usata per cancellare i caratteri iniziali dal nome di un file. Una barra è necessaria per ogni carattere da cancellare. Ho confermato il comportamento su una macchina Windows 10.
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
Questa tecnica funziona solo se entrambe le maschere di origine e di destinazione sono racchiuse tra doppi apici. Tutti i seguenti moduli senza le virgolette necessarie falliscono con questo errore: 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
Lo /
non può essere usato per rimuovere alcun carattere nel mezzo o alla fine di un nome di file. Può solo rimuovere i caratteri iniziali (prefisso). Notate anche che questa tecnica non funziona con i nomi delle cartelle.
Tecnicamente lo /
non funziona come un carattere jolly. Piuttosto sta facendo una semplice sostituzione di caratteri, ma poi dopo la sostituzione, il comando REN riconosce che /
non è valido in un nome di file, e rimuove le barre iniziali /
dal nome. REN dà un errore di sintassi se rileva /
nel mezzo di un nome di destinazione.
Possibile bug di RENAME - un singolo comando può rinominare lo stesso file due volte!
Inizio in una cartella di prova vuota:
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
Credo che la sourceMask *1*
corrisponda prima al nome lungo del file, e il file viene rinominato al risultato atteso di 223456789.123.x
. RENAME poi continua a cercare altri file da processare e trova il file appena nominato tramite il nuovo nome corto di 223456~1.X
. Il file viene poi rinominato di nuovo dando il risultato finale di 223456789.123.xx
.
Se disabilito la generazione del nome 8.3 allora il RENAME dà il risultato atteso.
Non ho elaborato completamente tutte le condizioni di attivazione che devono esistere per indurre questo strano comportamento. Ero preoccupato che potesse essere possibile creare un RENAME ricorsivo senza fine, ma non sono mai stato in grado di indurne uno.
Credo che tutte le seguenti condizioni debbano essere vere per indurre il bug. Ogni caso di bug che ho visto aveva le seguenti condizioni, ma non tutti i casi che soddisfacevano le seguenti condizioni erano bug.
- I nomi brevi 8.3 devono essere abilitati
- La sourceMask deve corrispondere al nome lungo originale.
- La rinomina iniziale deve generare un nome corto che corrisponda anche alla sourceMask
- Il nome corto iniziale rinominato deve essere successivo al nome corto originale (se esisteva?)