Deze regels zijn ontdekt na uitvoerige tests op een Vista-machine. Er zijn geen tests gedaan met unicode in bestandsnamen._
RENAME vereist 2 parameters - een sourceMask, gevolgd door een targetMask. Zowel de sourceMask als de targetMask kunnen *
en/of ?
jokertekens bevatten. Het gedrag van de jokertekens verschilt enigszins tussen bron- en doelmaskers.
Note - REN kan worden gebruikt om een map te hernoemen, maar jokertekens zijn niet toegestaan in zowel het bronMask als het doelMask bij het hernoemen van een map. Als de sourceMask overeenkomt met ten minste één bestand, dan wordt het bestand hernoemd en worden mappen genegeerd. Als de sourceMask alleen overeenkomt met mappen en niet met bestanden, dan wordt een syntaxisfout gegenereerd als jokertekens voorkomen in source of target. Als de sourceMask nergens mee overeenkomt, resulteert dat in een “bestand niet gevonden”-fout.
Ook bij het hernoemen van bestanden zijn jokertekens alleen toegestaan in het bestandsnaamgedeelte van de sourceMask. Jokertekens zijn niet toegestaan in het pad dat naar de bestandsnaam leidt.
sourceMask
De sourceMask werkt als een filter om te bepalen welke bestanden hernoemd worden. De jokertekens werken hier hetzelfde als bij elk ander commando dat bestandsnamen filtert.
?
- Komt overeen met elk 0 of 1 teken exclusief .
Dit jokerteken is hebzuchtig - het gebruikt altijd het volgende teken als dat geen .
is. Het zal echter zonder falen met niets overeenkomen als het aan het einde van de naam staat of als het volgende teken een .
*
- Komt overeen met elk 0 of meer tekens inclusief .
(met één uitzondering hieronder). Deze wildcard is niet gretig. Het komt overeen met zo weinig of zo veel als nodig is om volgende tekens overeen te laten komen.
Alle niet-wildcard tekens moeten met zichzelf overeenkomen, met een paar speciale uitzonderingen.
.
- Komt overeen met zichzelf of kan overeenkomen met het einde van de naam (niets) als er geen tekens meer over zijn. (Opmerking - een geldige Windows-naam kan niet eindigen op .
)
{space}
- Komt overeen met zichzelf of kan overeenkomen met het einde van de naam (niets) als er geen tekens meer over zijn. (Opmerking - een geldige Windows-naam kan niet eindigen op {space}
)
*.
aan het eind - Komt overeen met 0 of meer tekens uitgezonderd .
De afsluitende .
kan in feite elke combinatie van .
en {space}
zijn, zolang het allerlaatste teken in het masker maar .
is. Dit is de enige uitzondering waarbij *
niet simpelweg overeenkomt met een willekeurige reeks tekens.
De bovenstaande regels zijn niet zo ingewikkeld. Maar er is nog een zeer belangrijke regel die de situatie verwarrend maakt: De sourceMask wordt vergeleken met zowel de lange naam als de korte 8.3 naam (als die bestaat). Deze laatste regel kan de interpretatie van de resultaten erg lastig maken, omdat het niet altijd duidelijk is wanneer het masker wordt vergeleken via de korte naam.
Het is mogelijk om RegEdit te gebruiken om het genereren van korte 8.3 namen op NTFS volumes uit te schakelen, waardoor de interpretatie van de resultaten van het bestandsmasker veel eenvoudiger wordt. Alle korte namen die werden gegenereerd voordat de korte namen werden uitgeschakeld, blijven bestaan.
targetMask
Note - Ik heb geen strenge tests gedaan, maar het lijkt erop dat dezelfde regels ook werken voor de doelnaam van het COPY-commando
Het targetMask geeft de nieuwe naam aan. Het wordt altijd toegepast op de volledige lange naam; Het targetMask wordt nooit toegepast op de korte 8.3 naam, zelfs niet als het sourceMask overeenkomt met de korte 8.3 naam.
De aan- of afwezigheid van jokertekens in de sourceMask heeft geen invloed op de manier waarop jokertekens in de targetMask worden verwerkt.
In de volgende discussie - staat c
voor elk teken dat niet *
, ?
of .
is
De targetMask wordt strikt van links naar rechts tegen de bronnaam afgezet, zonder back-tracking.
c
- Gaat alleen vooruit in de bronnaam als het bronteken niet .
is, en voegt altijd c
toe aan de doelnaam. (Vervangt het teken dat in bron was door c
, maar vervangt nooit .
)
?
- Komt overeen met het volgende teken uit de lange bronnaam en voegt dit toe aan de doelnaam zolang het bronteken niet .
is Als het volgende teken .
is of als het aan het eind van de bronnaam is, wordt geen teken aan het resultaat toegevoegd en blijft de huidige positie binnen de bronnaam ongewijzigd.
*
aan einde van targetMask - Voegt alle resterende tekens van bron naar doel toe. Indien al aan het eind van bron, dan doet het niets.
*c
- Zoekt alle bron-tekens vanaf de huidige positie tot en met het laatste voorkomen van c
(hoofdlettergevoelige “greedy match”) en voegt de overeenkomende set tekens toe aan de doelnaam. Als c
niet wordt gevonden, worden alle resterende tekens van de bron toegevoegd, gevolgd door c
Dit is de enige situatie waarvan ik weet dat Windows bestandspatroonherkenning hoofdlettergevoelig is.
*.
- Zoekt alle bron-tekens vanaf de huidige positie tot en met het laatste voorkomen van .
(greedy match) en voegt de gematchte set van tekens aan de doelnaam. Als .
niet wordt gevonden, dan worden alle resterende karakters van bron toegevoegd, gevolgd door .
*?
- Voegt alle resterende karakters van bron toe aan het doel. Indien reeds aan het einde van bron, doet niets.
.
zonder *
ervoor - Gaat de positie in bron verder door het eerste voorkomen van .
zonder enige karakters te kopiëren, en voegt .
toe aan de doelnaam. Als .
niet in de bron wordt gevonden, gaat het verder naar het einde van de bron en voegt .
toe aan de doelnaam.
Nadat het doelMask is uitgeput, worden alle .
en {space}
aan het eind van de resulterende doelnaam weggeknipt, omdat Windows-bestandsnamen niet kunnen eindigen met .
of {space}
Enkele praktische voorbeelden
Vervang een teken op de 1e en 3e positie vóór een extensie (voegt een 2e of 3e karakter toe als het nog niet bestaat)
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
Wijzig de (uiteindelijke) extensie van elk bestand
ren * *.txt
a -> a.txt
b.dat -> b.txt
c.x.y -> c.x.txt
Voeg een extensie toe aan elk bestand
ren * *?.bak
a -> a.bak
b.dat -> b.dat.bak
c.x.y -> c.x.y.bak
Verwijder elke extra extensie na de initiële extensie. Merk op dat adequate ?
moet worden gebruikt om de volledige bestaande naam en initiële extensie te behouden.
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)
Hetzelfde als hierboven, maar filter bestanden met een initiële naam en/of extensie langer dan 5 karakters uit zodat ze niet worden afgekapt. (Uiteraard kan een extra ?
aan beide uiteinden van targetMask worden toegevoegd om namen en extensies tot 6 karakters lang te behouden)
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)
Verander karakters na laatste _
in naam en probeer extensie te behouden. (Werkt niet goed als er _
in de extensie staat)
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)
Elke naam kan worden opgedeeld in componenten die worden afgebakend door .
Tekens mogen alleen worden toegevoegd aan of verwijderd uit het eind van elk component. Tekens kunnen niet worden verwijderd uit of toegevoegd aan het begin of midden van een component met behoud van de rest met jokertekens. Substituties zijn overal toegestaan.
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
Als korte namen zijn ingeschakeld, dan zal een sourceMask met ten minste 8 ?
voor de naam en ten minste 3 ?
voor de extensie overeenkomen met alle bestanden, omdat het altijd overeenkomt met de korte 8.3 naam.
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
Handige quirk/bug? voor het verwijderen van naamvoorvoegsels
Deze SuperUser post beschrijft hoe een set voorwaartse schuine strepen (/
) gebruikt kan worden om voorloopkarakters uit een bestandsnaam te verwijderen. Eén schuine streep is nodig voor elk karakter dat verwijderd moet worden. Ik heb het gedrag bevestigd op een Windows 10-machine.
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
Deze techniek werkt alleen als zowel de bron- als doelmaskers tussen dubbele aanhalingstekens staan. Alle volgende formulieren zonder de vereiste aanhalingstekens falen met deze foutmelding: 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
De /
kan niet worden gebruikt om tekens in het midden of aan het eind van een bestandsnaam te verwijderen. Het kan alleen de voorloop (prefix) tekens verwijderen. Merk ook op dat deze techniek niet werkt met mapnamen.
Technisch gezien werkt de /
niet als een wildcard. Het doet eerder een eenvoudige tekenvervanging, maar na de vervanging herkent het REN commando dat /
niet geldig is in een bestandsnaam, en verwijdert de leidende /
schuine strepen uit de naam. REN geeft een syntaxisfout als het /
in het midden van een doelnaam detecteert.
Mogelijke RENAME fout - een enkel commando kan hetzelfde bestand twee keer hernoemen!
Beginnen in een lege testmap:
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
Ik denk dat het sourceMask *1*
eerst overeenkomt met de lange bestandsnaam, en het bestand wordt hernoemd naar het verwachte resultaat van 223456789.123.x
. RENAME gaat dan verder met zoeken naar meer bestanden om te verwerken en vindt het nieuw genoemde bestand via de nieuwe korte naam van 223456~1.X
. Het bestand wordt dan opnieuw hernoemd, met als eindresultaat 223456789.123.xx
.
Als ik 8.3 naamgeneratie uitschakel, geeft de RENAME het verwachte resultaat.
Ik heb nog niet alle triggervoorwaarden uitgewerkt die moeten bestaan om dit vreemde gedrag te veroorzaken. Ik was bang dat het mogelijk zou zijn om een nooit eindigende recursieve RENAME te maken, maar ik heb er nooit een kunnen induceren.
Ik geloof dat al het volgende waar moet zijn om de bug te veroorzaken. Elk geval met een bug dat ik zag, had de volgende voorwaarden, maar niet alle gevallen die aan de volgende voorwaarden voldeden, hadden een bug.
- Korte 8.3 namen moeten ingeschakeld zijn
- Het bronMasker moet overeenkomen met de oorspronkelijke lange naam.
- De initiële hernoeming moet een korte naam genereren die ook overeenkomt met de sourceMask
- De initiële hernoemde korte naam moet later sorteren dan de oorspronkelijke korte naam (als die al bestond?)