Эти правила были обнаружены после тщательного тестирования на компьютере с 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
Если короткие имена включены, то источникМаска с по крайней мере 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
- Исходное переименованное короткое имя должно быть отсортировано позже исходного короткого имени (если оно существовало?)