Почему работает «Get-ChildItem -File | Get-FileHa sh»? - PullRequest
7 голосов
/ 11 февраля 2020

Я больше знаком с Bash, чем с Powershell, и иногда меня смущает объектная модель последней.

Глядя на документацию Get-FileHa sh, кажется, что есть 3 способа задания ввода:

  • Get-FileHa sh [-Path]
  • Get-FileHa sh [-LiteralPath]
  • Get-FileHa sh [-InputStream]

Первые два берут имена файлов, третьи - поток данных.

Сейчас, Get-ChildItem -File , кажется, выводит System.IO.FileInfo объектов, судя по тому, что Get-Member говорит:

$ Get-ChildItem -File | Get-Member
TypeName: System.IO.FileInfo

И все же конвейер Get-ChildItem -File | Get-FileHash работает правильно. У меня вопрос: какой механизм позволяет преобразовать System.IO.FileInfo в тип входных данных, ожидаемый Get-FileHash?

Ответы [ 3 ]

8 голосов
/ 12 февраля 2020

System.IO.FileInfo / System.IO.DirectoryInfo экземпляры, выводимые командлетами PowerShell, имеют свойство .PSPath [*] , которое содержит полный путь к экземплярам, ​​то есть полный файл -системный путь с префиксом имени поставщика PS (например, Microsoft.PowerShell.Core\FileSystem::C:\windows).

Командлеты обработки файлов, такие как Get-FileHash, имеют параметр -LiteralPath с псевдонимом -PSPath.

Поскольку параметр -LiteralPath (обычно) принимает входные данные из конвейера по имени свойства , input объекты, имеющие свойство .PSPath, автоматически связываются с ним , благодаря псевдониму параметра PSPath.


Как обнаружить это поведение:

  • Через онлайн-справку topi c:

parameter description

  • Программно:

    • Примечание: Get-Help Get-FileHash -Parameter LiteralPath | Select-Object name, aliases, pipelineinput также работает в в этом случае, но этот подход обычно ограничен целевыми командами, которые поставляются с MAML - база d Файлы справки, и даже те, которые имеют, могут иметь файлы справки, которые не синхронизированы c с фактическим определением команды.
PS> & {
        Get-Command $args[0] | % Parameters | % $args[1] |
        Select-Object Name, Aliases, @{
            n = 'Accepts pipeline input';
            e = { $(if ($_.Attributes.ValueFromPipeline) { 'by value' }), $(if ($_.Attributes.ValueFromPipelineByPropertyName) { 'by property name' }) -join ', ' -replace '^, ' }
        }
    } Get-FileHash LiteralPath


Name        Aliases      Accepts pipeline input
----        -------      ----------------------
LiteralPath {PSPath, LP} by property name

[*] Это поставщик файловой системы PowerShell, который, помимо прочего, добавляет это свойство. Базовые типы. NET имеют , а не . См. этот ответ для получения дополнительной информации.

3 голосов
/ 12 февраля 2020

Из документации «О расширенных параметрах функций» ValueFromPipelineByPropertyName секция аргумента :

Аргумент ValueFromPipelineByPropertyName указывает, что параметр принимает входные данные из свойства объекта трубопроводный объект. Свойство объекта должно иметь то же имя или псевдоним, что и параметр.

Например, если функция имеет параметр ComputerName, а переданный объект имеет свойство ComputerName, значение свойства ComputerName присваивается Параметр ComputerName функции.

Обновление : Первоначально связан неверный файл исходного кода. Правильный исходный код Get-FileHash находится здесь . Поскольку @ mklement0 правильно ответил , Get-ChildItem командлет выводит объект со свойством PSPath, что делает эту работу.

0 голосов
/ 12 февраля 2020

Похоже, он использует свойство pspath.

dir there | select pspath | get-filehash

Algorithm  Hash                                                                Path
---------  ----                                                                ----
SHA256     44723DD4D0E0D46A3C7FA8ACA254B61C27B6B5789F96177E82C80700409F1535    C:\users\...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...