Confused with -Include параметр командлета Get-ChildItem

Из документации:

-Include

Извлекает только указанные элементы. Значение этого параметра соответствует параметр Path. Введите путь элемент или шаблон, например "*.txt". Подстановочные знаки разрешены.

Параметр Include эффективен только тогда, когда команда включает параметр Recurse или путь приводит к содержанию каталог, такой как C:\Windows *, где подстановочный знак указывает содержимое каталога C:\Windows.

Мое первое понимание:

c:\test\a.txt
c:\test\b.txt

Итак, чтобы получить "a.txt" и "b.txt", я могу написать:

gci -Path "c:\test\*" -Include "*.txt"

И это работает. Но теперь рассмотрим такую ​​иерархию:

c:\test\a.txt
c:\test\b.txt
c:\test\c.txt\c.txt

Эта же команда возвращает:  a.txt, b.txt, c.txt

Фактическая логика выглядит следующим образом:

-Include используется для соответствия всем объектам, указанным -Path. Если согласованный элемент это файл - вернуть его. Если сопоставлено элемент - это папка, загляните внутрь и возвращать соответствующие дети первого уровня.

Кроме того, в документации говорится:

Параметр Include эффективен только тогда, когда команда включает параметр Recurse или путь приводит к содержанию каталог...

Это неправильно. Например.

gci -Path "c:\test" -Include "*.txt"

Он ничего не возвращает, а без -Include я получаю содержимое папки. Итак -Include определенно "эффективен". Что на самом деле происходит здесь? Параметр -Path указывает "c:\test", а -Include пытается сопоставить этот путь. Поскольку "*.txt" не соответствует "test", поэтому ничего не возвращается. Но посмотрите на это:

gci -Path "c:\test" -Include "*t"

Он возвращает a.txt, b.txt и c.txt как "* t", соответствующий "test" и сопоставляет все дочерние элементы.

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

Ответ 1

Вы запутываете использование -include. Флаг -include применяется к пути, а не содержимому пути. Без использования рекурсивного флага единственный путь, о котором идет речь, - это указанный вами путь. Вот почему в последнем примере, который вы дали, путь c:\test имеет t в пути и, следовательно, соответствует "*t".

Вы можете проверить это, попробовав следующие

gci -path "c:\test" -in *e*

Это все равно приведет к появлению всех дочерних элементов в каталоге, но не соответствует ни одному из них.

Причиной того, что -include является более эффективным с параметром recurse, является то, что вы в конечном итоге применяете шаблон для каждого пути в иерархии.

Ответ 2

Попробуйте параметр -filter (он поддерживает только одно расширение):

dir -filter *.txt

Ответ 3

Отвечая на ответ JaredPar, чтобы выполнить сопоставление образцов с Get-ChildItem, вы можете использовать общие групповые символы оболочки.

Например:

get-childitem "c:\test\t?st.txt"

где "?" является подстановочным знаком, соответствующим любому символу или

get-childitem "c:\test\*.txt"

который будет соответствовать любому имени файла, заканчивающегося на ".txt".

Это должно помочь вам найти более простое поведение.

Ответ 4

Я просто задал аналогичный вопрос и получил три быстрых ответа относительно Get-Help для Get-ChildItem.

Ответ в полном описании команды (Get-Help Get-ChildItem -full):

The Include parameter is effective only when the command includes the

Параметр Recurse или путь ведет к содержимое каталога, например, C:\Windows *, где шаблон character указывает содержимое каталог C:\Windows.

Таким образом, следующее будет работать без рекурсию.

PS C:\foo > Get-childitem -path "c:\foo *" -Include *.txt

Из вопроса о переполнении стека PowerShell Scripting - Get-ChildItem.

Надеюсь, это поможет: -)

Ответ 5

Включение \* в конце пути должно обойти проблему

PS C:\logfiles> Get-ChildItem .\* -include *.log

Это должно возвращать файлы .log из текущего рабочего каталога (C:\logfiles)

Пример Alex показывает, что также будет возвращен каталог с именем foo.log. Когда я попробовал это, это было не то, но через 6 лет, и это может быть из обновлений PS.

Однако вы можете использовать дочерний элемент Mode для исключения каталогов, которые, как я думаю.

PS C:\logfiles> Get-Childitem .\* -include *.log | where-object {$_.mode -notmatch "d"}

Это должно исключать что-либо с установленным режимом "каталог".

Ответ 6

get-childitem -include работает только с -recursive или подстановочным знаком в пути. Я считаю это ошибкой [Хотя в PS 6 все было по-другому].