Для предотвращения случайного переименования уже переименованных файлов повторного ввода перечисления файлов и, следовательно, его переименования многократного раза, заключает ваш Get-ChildItem
вызов в ()
оператор группировки , который гарантирует, что весь вывод собран первый [1] , перед отправкой результатов по конвейеру:
(Get-ChildItem -Recurse) |
Rename-Item -NewName { $_.name -replace '\.txt$', '_old.txt' }
Обратите внимание, что я использовал \.txt$
в качестве регулярного выражения [2] , чтобы гарантировать, что за литералом .
(\.
) следует строка txt
в конце ($
) имени файла сопоставляется, чтобы предотвратить ложные срабатывания (например, файл с именем Atxt.csv
или даже каталог с именем * 1032) * случайно совпадет с вашим исходным регулярным выражением).
Примечание. Необходимость сначала собрать все выходные данные Get-ChildItem
возникает из-за фундаментальной работы конвейера PowerShell: объекты (по умолчанию) отправляются в конвейер one на один и обрабатывается принимающей командой по мере их eived . Это означает, что без (...)
вокруг Get-ChildItem
, Rename-Item
начинает переименовывать файлы до того, как Get-ChildItem
завершит перечисление файлов, что вызывает проблемы. См. этот ответ для получения дополнительной информации о том, как работает конвейер PowerShell.
Подсказка к Мэтью для предложения включения этой информации.
Однако я предлагаю оптимизировать вашу команду следующим образом:
(Get-ChildItem -Recurse -File -Filter *.txt) |
Rename-Item -NewName { $_.BaseName + '_old' + $_.Extension }
-File
ограничивает вывод в файлы (также не возвращает каталогов ).
-Filter
- это самый быстрый способ ограничить результаты заданным шаблоном подстановки.
$_.BaseName + '_old' + $_.Extension
использует простую конкатенацию строк через подкомпоненты имени файла.
- Альтернативой является использование
-replace
:
$_.Name -replace '\.[^.]+$', '_old$&'
Примечание что если вы хотите выполнить это несколько раз и хотите исключить файлы, переименованные в предыдущем запуске, добавьте -Exclude *_old.txt
к вызову Get-ChildItem
.
[1] из-за изменения в как Get-ChildItem
реализован в PowerShell [Core] 6 + (теперь он внутренне сортирует результаты, что неизменно требует сбора Прежде всего, (...)
корпус больше не является строго необходимым , но это можно рассматривать как деталь реализации, поэтому для концептуальной ясности лучше продолжать использовать (...)
.
[2] Оператор PowerShell -replace
работает с регулярными выражениями (регулярные выражения); он не выполняет подстроку literal , которая ищет метод .Replace()
типа [string]
.