Get-Content не в скобках - доступ к процессу запрещен - PullRequest
2 голосов
/ 19 июня 2019

При использовании Get-Content для удаления пробелов из файла:

$file = "C:\Folder\MyFile001.txt"
Get-Content -Path $file | ? { -not [string]::IsNullOrWhiteSpace($_) } | Set-Content -Path $file

Отображает сообщение об ошибке «Set-Content: процесс не может получить доступ к файлу» ..., поскольку он используется другим процессом.

Исправлено использование скобок с Get-Content:

(Get-Content -Path $file) | ...

В чем причина этого? Я хотел бы понять, в чем разница, заключенная в скобки, и относится ли это к другим командлетам.

Ответы [ 2 ]

4 голосов
/ 19 июня 2019

Когда командлет выводит что-то в конвейер, конвейер выполняется до обработки следующего вывода командлета.Таким образом, поскольку ваша строка работает по конвейеру до Set-Content, Get-Content все еще активен (с открытым выходным файлом), ожидая своей очереди на продолжение выполнения.Однако когда вы заключаете выражение в (), все выходные данные собираются в массив, который затем передается по конвейеру.Get-Content готово и файл закрыт.Чтобы продемонстрировать, рассмотрим эту функцию:

function get-10dates { $count = 0; while($count -lt 10){ get-date; $count += 1 }}

, когда вы запускаете ее и передаете ее в цикл foreach:

get-10dates | foreach { $_; sleep -Seconds 1 }

, вы получаете следующий вывод, каждая дата которого задерживается насекунда, из-за sleep в foreach:

# ~> get-10dates | foreach { $_; sleep -Seconds 1 }

June 19, 2019 9:58:36 AM
June 19, 2019 9:58:37 AM
June 19, 2019 9:58:38 AM
June 19, 2019 9:58:39 AM
June 19, 2019 9:58:40 AM
June 19, 2019 9:58:41 AM
June 19, 2019 9:58:42 AM
June 19, 2019 9:58:43 AM
June 19, 2019 9:58:44 AM
June 19, 2019 9:58:45 AM

Теперь, если вы оберните функцию в ().Вы можете видеть, что все 10 дат создаются одновременно (в течение 1 секунды), прежде чем они будут переданы по конвейеру:

# ~> (get-10dates) | foreach { $_; sleep -Seconds 1 }

June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
June 19, 2019 9:58:53 AM
0 голосов
/ 19 июня 2019

Скобки в Powershell работают так же, как и в алгебре.

Вид.

PowerShell сначала выполняет команду в скобках, а затем пытается сопоставить ее с тем, куда она идет.В этом случае вы говорите ему завершить запуск Get-Content и считывать буфер в память, прежде чем он перейдет к следующей команде, вместо того, чтобы передавать все по каналу.

Это похоже на то, как работает BaSH, когда вы используете что-то вроде (при условии, что «service.txt» содержит одну строку, которая говорит apache):

Service $(cat /etc/service.txt) Stop
>> Service apache stop 

, которая будет выполнять команду в$ () и вернуть его в виде текста перед выполнением остальной части команды.

В PowerShell вы можете использовать возможности сопоставления типов в круглых скобках, чтобы сделать изящные вещи, например, заставить его возвращать только одно свойство объекта:

(Get-ChildItem -filter "*.pdf" -Path .\Projects).FullName 
>> C:\Users\ncf\Projects\Documentation.pdf
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...