#.net #powershell #powershell-7.0
#.net #powershell #powershell-7.0
Вопрос:
Используя Powershell 7, это работает отлично:
dir foo* | Rename-Item -Path {$_.Name} -NewName{$_.Name -replace 'bar-(.*)', 'bar-$1'}
Это не удается:
dir foo* | Rename-Item {$_.Name} {$_.Name -replace 'bar-(.*)', 'bar-$1'}
Со следующей ошибкой:
Rename-Item: A positional parameter cannot be found that accepts argument '$_.Name'.
Основываясь на документах, вот -Path
первая позиция Rename-Item
. Кроме того, работает следующая команда: Rename-Item 'foo-one' 'foo-one-one'
. Почему происходит вышеупомянутый сбой?
Комментарии:
1. @AdminOfThings почти правильно,
dir
это псевдоним, наGet-ChildItem
который выводится объект со свойством PSPath.Rename-Item
Функция использует PSPath в качестве псевдонима для параметра LiteralPath , поэтому вы фактически используете другой набор параметров (который не включает -Path ).2. @Dabombber Это имеет наибольший смысл, поскольку пропуск {$_.Name} фактически заставляет команду работать. Не стесняйтесь публиковать его в качестве ответа.
3. @iRon Когда я это делаю, это дает мне неожиданный результат, показывающий фоновые задания. Предполагается ли, что <ScriptBlock> преобразуется в <string> ?
Ответ №1:
Хотя ваш пример кода на самом деле не переименовывает ни один файл ( -replace 'bar-(.*)', 'bar-$1'
приведет к точно такому же имени.), Основная проблема здесь заключается в том, что вы добавляете {$_.Name}
непосредственно после Rename-Item
командлета, где это не требуется, поскольку вы уже передаете объекты FileInfo по конвейеру, поэтому now {$_.Name}
обрабатывается так, как если бы это былимя параметра.
Затем вы забываете добавить имя для параметра -NewName
.
Повторяя путь, подобный foo*
тому, который вы делаете, так же, как -Path 'foo' -Recurse
и, и в этом есть ошибка..
Особенно при переборе множества файлов и передаче их по конвейеру, есть вероятность, что файлы, которые уже были переименованы, снова будут выбраны Get-ChildItem
(псевдонимом dir
), а затем будут переименованы дважды.
Чтобы преодолеть это, поместите часть для сбора файлов в квадратные скобки, чтобы сбор всех объектов FileInfo был завершен, а затем передайте это следующему командлету следующим образом:
(Get-ChildItem -Path 'foo' -File -Recurse) |
Rename-Item -NewName {$_.Name -replace 'bar-(.*)', 'baz-$1'}
для наглядности это меняет часть имени с bar
на baz