Результаты Get-ChildItem выглядят как относительные пути в Powershell - PullRequest
4 голосов
/ 03 августа 2011

Я хотел бы сканировать и перемещать папки (и подпапки или даже глубже) из одной папки в другую, используя Powershell.

В настоящее время я использую этот канал команд.

Get-ChildItem  -recurse  -path sub\WORK  -filter "* OK" | Where-Object { $_.PSIsContainer } | foreach { Move-Item -path $_  -destination sub\OK }

К сожалению, это не работает, потому что найденные результаты относятся к .\sub\WORK, при попытке их переместить Move-Item жалуется, что папки не находятся в текущей папке:

Move-Item : Cannot find path 'C:\TMP\2011-12-12 test 2 OK' because it does not exist.

Я ожидаю, что $ _ будет содержать: 'C:\TMP\sub\WORK\2011-12-12 test 2 OK', потому что это объекты в Powershell, а не строки, как в Linux.

Ответы [ 4 ]

5 голосов
/ 03 августа 2011

Если вы используете Get-ChildItem, будьте очень осторожны.Лучший способ - передать объекты на Move-Item, и вам не нужно больше об этом думать:

Get-ChildItem  -recurse  -path sub\WORK  -filter "* OK" | Where-Object { $_.PSIsContainer } | Move-Item -destination sub\OK

(не нужно использовать Foreach-Object)

ОсновнойПричина, по которой я отвечаю, заключается в следующем: Get-ChildItem конструирует объект по-разному, в зависимости от параметров.Посмотрите на примеры:

PS C:\prgs\tools\Console2> gci -include * | % { "$_" } | select -fir 5
C:\prgs\tools\Console2\-verbose
C:\prgs\tools\Console2\1UpdateDataRepositoryServices.ps1
C:\prgs\tools\Console2\22-52-59.10o52l
C:\prgs\tools\Console2\2jvcelis.ps1
C:\prgs\tools\Console2\a
PS C:\prgs\tools\Console2> gci | % { "$_" } | select -fir 5
-verbose
1UpdateDataRepositoryServices.ps1
22-52-59.10o52l
2jvcelis.ps1
a

Тогда, если вы используете $_ в цикле и PowerShell необходимо преобразовать FileInfo из Get-ChildItem в строку, это даст разные результаты.Это произошло, когда вы использовали $_ в качестве аргумента для Move-Item.Довольно плохо.

Я думаю, что есть ошибка, сообщающая об этом поведении.

3 голосов
/ 03 августа 2011

Вы правы, что объекты передаются по конвейеру вместо строк.Это хорошо тем, что он более гибкий.Недостатком является то, что если вы не укажете системе в явном виде, какое свойство объекта использовать, вы получите от власти разработчиков системы.Посмотрите, поможет ли явное указание системе требуемого свойства:

Get-ChildItem  -recurse  -path sub\WORK  -filter "* OK" | Where-Object { $_.PSIsContainer } | foreach { Move-Item -path $_.Fullname  -destination sub\OK }
2 голосов
/ 03 августа 2011

Я просто узнал, что PSPath автоматически используется в Copy-Item, Move-Item и т. Д., Когда вы не указываете источник в конвейере, так что-то вроде:

gci .\sub\Work | move-item -Destination .\sub\OK

(упрощенный пример)

будет работать и будет использовать PSPath переданного объекта для определения источника.


Так как Get-ChildItem возвращает объекты, как вы сказали,вы можете использовать Get-Member, чтобы увидеть, что объект может предложить (то есть знать о его свойствах и методах)

 Get-ChileItem path | Get-Member

Вы можете увидеть, что FullName является одним из свойств, которые вы можете использовать.

0 голосов
/ 26 ноября 2014

Вот что у меня сработало.

Get-ChildItem -Path .\ -Recurse -filter "* OK" | %{Join-Path -Path $_.Directory -ChildPath $_.Name } | Move-Item -Destination sub\OK
...