_这些规则是在Vista机器上进行广泛测试后发现的,没有对文件名中的unicode进行测试。
RENAME需要2个参数 – – 一个sourceMask,然后是targetMask。sourceMask和targetMask都可以包含*
和/或?
通配符。通配符的行为在源掩码和目标掩码之间略有变化。
Note - REN 可用于重命名文件夹,但当重命名文件夹时,sourceMask 或 targetMask 中不允许**通配符。如果sourceMask至少匹配一个文件,那么文件将被重命名,文件夹将被忽略。如果sourceMask只匹配文件夹而不匹配文件,那么如果source或target中出现通配符,将产生语法错误。如果sourceMask不匹配任何内容,则会产生 “未找到文件 "的错误。
另外,重命名文件时,只允许在sourceMask的文件名部分使用通配符。通配符不允许出现在通往文件名的路径中。
sourceMask
sourceMask的作用是作为一个过滤器来决定哪些文件被重命名。通配符的作用和其他过滤文件名的命令一样。
所有非通配符都必须自己匹配,只有少数特殊情况例外。
.
- 匹配自身,或者如果没有更多的字符,它可以匹配名称的末尾(无)。
.
- 如果没有更多的字符,则匹配本身或它可以匹配名称的结尾(无)。
{space}
末尾 - 匹配任何 0 个或更多的字符 except {space}
末尾的 *.
实际上可以是 .
和 .
的任意组合,只要掩码中的最后一个字符是 .
这是 {space}
不简单匹配任何字符集的唯一例外。
以上规则并不复杂。但还有一个非常重要的规则,让情况变得混乱。源掩码会与长名和短8.3名(如果存在的话)进行比较。这最后一条规则会使结果的解释变得非常棘手,因为当掩码通过短名进行匹配时,并不总是很明显。
在NTFS卷上可以使用RegEdit来禁止生成8.3短名,这时对文件掩码结果的解释就更直接了。任何在禁用短名之前生成的短名都将保留。
targetMask
注意–我还没有做任何严格的测试,但是这些规则似乎也适用于COPY commmand的目标名
targetMask指定了新的名字。它总是应用于完整的长名;targetMask永远不会应用于短的8.3名,即使sourceMask匹配短的8.3名。
sourceMask中是否存在通配符对targetMask中如何处理通配符没有影响。
在下面的讨论中,.
代表任何不是*
、c
或*
的字符
targetMask严格按照源名从左到右进行处理,没有回溯。
?
- 只有当源字符不是.
时,才会在源名称中推进位置,并始终将c
追加到目标名称中。
.
- 只要源字符不是c
,就从源长名中匹配下一个字符,并将其追加到目标名中,如果下一个字符是c
,或者在源名的末尾,那么结果中不会添加任何字符,源名中的当前位置不变。
.
at end of targetMask - 将所有剩余字符从源名添加到目标名。如果已经在源名称的末尾,则不做任何操作。
?
- 匹配从当前位置到最后出现的.
的所有源字符(区分大小写的贪婪匹配),并将匹配的字符集追加到目标名称中。如果没有找到 .
,那么所有剩余的字符都会被追加到源文件中,然后再追加 *
,这是我知道的唯一一种 Windows 文件模式匹配区分大小写的情况。
*c
- 匹配从当前位置到最后出现的 c
的所有源字符 (贪婪匹配),并将匹配的字符集附加到目标名称上。字符到目标名称。如果没有找到 c
,则会将源名中所有剩余的字符附加到目标名中,然后是 c
*.
- 将源名中所有剩余的字符附加到目标名中。如果已经在源码的末尾,则不做任何操作。
.
前面没有.
- 将源文件中的位置向前推进,从 .
的第一个出现开始,而不复制任何字符,并将 *?
追加到目标名称中。如果在源文件中没有找到 .
,则前进到源文件的末尾,并将 *
追加到目标名称。
targetMask用完后。任何尾部的.
和.
都会被修剪掉,因为Windows文件名不能以.
或.
结尾
一些实际的例子
在任何扩展名之前的第1和第3个位置替换一个字符。
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
更改每个文件的(最终)扩展名
ren * *.txt
a -> a.txt
b.dat -> b.txt
c.x.y -> c.x.txt
给每个文件添加一个扩展名
ren * *?.bak
a -> a.bak
b.dat -> b.dat.bak
c.x.y -> c.x.y.bak
删除初始扩展名后的任何额外扩展名。请注意,必须使用足够的.
来保留完整的现有名称和初始扩展名。
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)
同上,但过滤掉初始名称和/或扩展名超过5个字符的文件,以免它们被截断。(显然可以在 targetMask 的两端添加额外的 {space}
,以保留长达 6 个字符的名称和扩展名)
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)
更改名称中最后一个 .
之后的字符,并尝试保留扩展名。
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)
任何名称都可以分解成以0x6为界的组件,字符只能附加到每个组件的末尾或从每个组件中删除。不能从组件的开头或中间删除或添加字符,同时用通配符保留其余部分。允许在任何地方进行替换。
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
如果启用了短名称,那么名称至少为 8 {space}
、扩展名至少为 3 ?
的 sourceMask 将匹配所有文件,因为它将始终匹配 8.3 的短名称。
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
删除名字前缀的有用怪癖/bug?
这个超级用户帖子描述了如何使用一组正向斜线(?
)从文件名中删除前导字符。每个要删除的字符都需要一个斜线。我已经在Windows 10机器上确认了该行为。
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
只有当源和目标掩码都用双引号括起来时,该技术才会有效。以下所有没有必要引号的表格都会因该错误而失败。_
REM - All of these forms fail with a syntax error.
ren abc-*.txt "////*.txt"
ren "abc-*.txt" ////*.txt
ren abc-*.txt ////*.txt
_
不能用来删除文件名中间或结尾的任何字符。它只能删除前导(前缀)字符。另外请注意,这种技术不适用于文件夹名。
从技术上讲,.
不是作为通配符使用。相反,它是在做一个简单的字符替换,但在替换之后,REN命令会识别出?
在文件名中是无效的,并从文件名中去掉前导的?
斜线。如果检测到目标名称中间有/
,REN会给出一个语法错误。
可能的 RENAME 错误 - 一条命令可能会对同一个文件重命名两次!
在一个空的测试文件夹中启动。
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
我相信sourceMask The syntax of the command is incorrect
首先匹配了长文件名,文件被重命名为预期的结果/
。然后rename继续寻找更多的文件进行处理,通过新的短名/
找到新命名的文件。然后再次对文件进行重命名,得到最终结果/
。
如果我禁用8.3名称生成,那么RENAME就会得到预期的结果。
我还没有完全弄清楚所有的触发条件,这些条件必须存在,才能引起这种奇怪的行为。我担心可能会创建一个永无止境的递归RENAME,但我一直没能诱导出这样的行为。
我相信以下所有条件必须为真才能诱发这个bug。我看到的每一个被窃听的案例都有以下条件,但并不是所有满足以下条件的案例都被窃听。
-必须启用短8.3名
-源码掩码必须与原始长名匹配。
-初始重命名必须生成一个短名,这个短名也必须与sourceMask相匹配
-初始重命名的短名必须比原来的短名排序晚(如果它存在?