Эти правила были обнаружены после тщательного тестирования на компьютере с Vista. С юникодом в именах файлов не проводилось никаких тестов.
RENAME требует 2 параметра - sourceMask, за которым следует targetMask. И sourceMask, и targetMask могут содержать *
и / или ?
шаблоны. Поведение групповых символов немного меняется между исходной и целевой масками.
Примечание - REN может быть использован для переименования папки, но подстановочные символы не допускается ни в sourceMask или targetMask при переименовании папки. Если sourceMask соответствует хотя бы одному файлу, файлы будут переименованы, а папки будут игнорироваться. Если sourceMask соответствует только папкам, а не файлам, генерируется синтаксическая ошибка, если в источнике или цели появляются символы подстановки. Если sourceMask не совпадает ни с чем, возникает ошибка «файл не найден».
Кроме того, при переименовании файлов подстановочные знаки допускаются только в части имени файла в SourceMask. Подстановочные знаки не допускаются в пути, ведущем к имени файла.
sourceMask
SourceMask работает как фильтр, чтобы определить, какие файлы переименованы. Подстановочные знаки работают здесь так же, как и с любой другой командой, которая фильтрует имена файлов.
?
- Соответствует любому символу 0 или 1, кроме .
этого подстановочного знака, является жадным - он всегда потребляет следующий символ, если он не является. .
Однако он не будет ничего совпадать без ошибок, если в конце имени или если следующий символ является.
*
- Соответствует любым 0 или более символам, включая .
(с одним исключением ниже). Этот подстановочный знак не жадный. Он будет соответствовать так мало или столько, сколько необходимо для соответствия последующих символов.
Все не подстановочные знаки должны совпадать, за исключением нескольких особых случаев.
.
- Соответствует самому себе или может соответствовать концу имени (ничего), если больше не осталось символов. (Примечание: действительное имя Windows не может заканчиваться .
)
{space}
- Соответствует самому себе или может соответствовать концу имени (ничего), если больше не осталось символов. (Примечание: действительное имя Windows не может заканчиваться {space}
)
*.
в конце - Соответствует любым 0 или более символам, за исключением .
завершающего символа, который .
может быть любой комбинацией .
и {space}
до тех пор, пока самый последний символ в маске равен. .
Это единственное исключение, в котором *
не просто совпадает ни один набор символов.
Вышеуказанные правила не так сложны. Но есть еще одно очень важное правило, которое запутывает ситуацию: SourceMask сравнивается как с длинным, так и с коротким именем 8.3 (если оно существует). Последнее правило может усложнить интерпретацию результатов, потому что не всегда очевидно, когда маска соответствует короткому имени.
Можно использовать RegEdit, чтобы отключить генерацию коротких имен 8.3 на томах NTFS, после чего интерпретация результатов маски файла становится гораздо более простой. Любые короткие имена, которые были созданы до отключения коротких имен, останутся.
targetMask
Примечание. Строгое тестирование не проводилось, но, похоже, эти же правила работают и для целевого имени команды COPY.
TargetMask указывает новое имя. Это всегда применяется к полному длинному имени; TargetMask никогда не применяется к короткому имени 8.3, даже если sourceMask соответствует короткому имени 8.3.
Наличие или отсутствие подстановочных знаков в sourceMask не влияет на то, как подстановочные знаки обрабатываются в targetMask.
В последующем обсуждении - c
любой символ , который не является *
, ?
или.
TargetMask обрабатывается относительно имени источника строго слева направо без обратного отслеживания.
c
- Продвигает позицию в пределах имени источника до тех пор, пока следующий символ не будет, .
и добавляется c
к целевому имени. (Заменяет символ, который был в источнике c
, но никогда не заменяет .
)
?
- Соответствует следующему символу из длинного имени источника и добавляет его к целевому имени до тех пор, пока следующий символ не будет. .
Если следующий символ .
или, если в конце имени источника, то ни один символ не добавляется к результату и текущему позиция в названии источника не изменилась.
*
в конце targetMask - добавляет все оставшиеся символы от источника к цели. Если уже в конце источника, то ничего не делает.
*c
- Сопоставляет все исходные символы от текущей позиции до последнего вхождения c
(жадное совпадение с учетом регистра) и добавляет соответствующий набор символов к целевому имени. Если c
он не найден, то добавляются все оставшиеся символы из источника, после чего следует « c
Это единственная известная мне ситуация, когда при сопоставлении шаблонов файлов Windows учитывается регистр символов».
*.
- Сопоставляет все исходные символы от текущей позиции до последнего вхождения .
(жадное совпадение) и добавляет соответствующий набор символов к целевому имени. Если .
не найден, то все остальные символы из источника добавляются, а затем.
*?
- Добавляет все оставшиеся символы от источника к цели. Если уже в конце источника, то ничего не делает.
.
без *
впереди - продвигает позицию в источнике через первое вхождение .
без копирования каких-либо символов и добавляет .
к целевому имени. Если .
он не найден в источнике, он переходит к концу источника и добавляется .
к целевому имени.
После того, как targetMask был исчерпан, любые конечные .
и {space}
обрезанные в конце конечного имени цели, потому что имена файлов Windows не могут заканчиваться .
или{space}
Некоторые практические примеры
Замените символ в 1-й и 3-й позициях перед любым расширением (добавляет 2-й или 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, чтобы сохранить имена и расширения длиной до 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)
Любое имя может быть разбито на компоненты, разделенные .
символами, которые могут быть добавлены или удалены только в конце каждого компонента. Символы не могут быть удалены или добавлены в начало или в середину компонента, сохраняя остаток с подстановочными знаками. Замены разрешены где угодно.
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
Если короткие имена включены, то sourceMask с по крайней мере 8 ?
для имени и по крайней мере 3 ?
для расширения будет соответствовать всем файлам, потому что оно всегда будет соответствовать короткому имени 8.3.
ren ????????.??? ?x.????999.*rForTheCourse
part1.part2.part3.part4 -> px.part999.part3.parForTheCourse
Полезная причуда / ошибка? для удаления префиксов имен
Этот пост SuperUser описывает, как набор косых черт ( /
) может быть использован для удаления начальных символов из имени файла. Для удаления каждого символа требуется один слеш. Я подтвердил поведение на компьютере с Windows 10.
ren "abc-*.txt" "////*.txt"
abc-123.txt --> 123.txt
abc-HelloWorld.txt --> HelloWorld.txt
Этот метод работает, только если исходная и целевая маски заключены в двойные кавычки. Все следующие формы без нужных кавычек завершаются с этой ошибкой: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
/
Не может быть использован для удаления любых символов в середине или в конце имени файла. Он может удалять только начальные (префиксные) символы.
Технически /
это не работает как подстановочный знак. Скорее, он выполняет простую подстановку символов, но затем после подстановки команда 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 *1*
сначала соответствует длинному имени файла, и файл переименовывается в ожидаемый результат 223456789.123.x
. Затем RENAME продолжает поиск файлов для обработки и находит новый файл с новым коротким именем 223456~1.X
. Затем файл снова переименовывается, давая окончательный результат 223456789.123.xx
.
Если я отключу генерацию имени 8.3, то RENAME даст ожидаемый результат.
Я не полностью проработал все условия триггера, которые должны существовать, чтобы вызвать это странное поведение. Я был обеспокоен тем, что возможно создать бесконечное рекурсивное RENAME, но я так и не смог вызвать его.
Я считаю, что все следующее должно быть правдой, чтобы вызвать ошибку. В каждом случае ошибки, который я видел, были следующие условия, но не все случаи, которые удовлетворяли следующим условиям, были ошибками.
- Короткие 8.3 имена должны быть включены
- SourceMask должен соответствовать оригинальному длинному имени.
- Первоначальное переименование должно генерировать короткое имя, которое также соответствует sourceMask
- Исходное переименованное короткое имя должно быть отсортировано позже исходного короткого имени (если оно существовало?)