PowerShell, Get-ChildItem с выходом -Depth - PullRequest
3 голосов
/ 03 марта 2020

Меня немного смущает флаг -Depth для Get-ChildItem. Следующее прекрасно работает (находит все файлы и папки только в одной глубине под "C: \ Program Files"):

dir 'C:\Program Files\' -Depth 1

Но если я захочу расширить его, чтобы найти только файлы типа * .txt Я не могу найти, как это сделать (следуя просто дать странно неожиданный вывод, где -Depth 1 игнорируется, и вместо этого он делает эквивалент от -Recurse до все подпапки независимо от того, насколько глубоко):

dir 'C:\Program Files\*.txt' -Depth 1
dir 'C:\Program Files\' -Include *.txt -Depth 1
dir 'C:\Program Files\*' -Include *.txt -Depth 1

Как мы используем -Depth для заданной c глубины для Get-ChildItem и необходимого шаблона файла?

Ответы [ 4 ]

2 голосов
/ 03 марта 2020

Вы видите поведение ошибка в Windows PowerShell , которое с тех пор исправлено в PowerShell [Core] 6 + - см. эту проблему GitHub .

Учитывая, что Windows PowerShell больше не разрабатывается активно, маловероятно, что ошибка будет исправлена.

Чтобы объяснить это, Windows PowerShell игнорирует ограничение глубины -Depth в следующих случаях :

  • с -Include или -Exclude
  • , если (подразумеваемый) аргумент -Path содержит символы подстановки.

Пока рекурсия все еще выполняется, без ограничения глубины навязывается; в действительности -Depth ведет себя как -Recurse (один) в этих случаях.

Обходные пути :

  • Для -Include и подстановочных знаков -Path аргументы, где подстановочные знаки ограничены последним компонентом пути:

    • Используйте взамен -Filter, как показано в Ответ Васиф Хасана .
    • Предостережение : -Filter обычно предпочтительнее в любом случае для его превосходной производительности, но его язык подстановочных знаков менее мощен , чем PowerShell и имеет устаревшие причуды - в частности, наборы символов и диапазоны ([...]) не поддерживаются и в Windows PowerShell фильтр, такой как *.xls, также соответствует *.xlsx файлам, для экземпляр - см. этот ответ .
  • для -Exclude:

    • Использовать только -Depth и выполнять фильтрацию после факт с Where-Object вызовом; например,
      Get-ChildItem -File 'C:\Program Files\' -Depth 1 | Where-Object Name -NotLike *.txt
  • [вероятно, редко требуется] Для основанных на подстановочных знаках -Path аргументов с подстановочными знаками (также) в компоненте прочее * На 1095 * больше, чем последний (например, C:\foo*\bar)

    • Используйте -Recurse и выполните фильтрацию по факту с помощью Where-Object; в этом случае вам также придется отсеивать слишком глубокие пути, подсчитывая количество их компонентов.
2 голосов
/ 03 марта 2020

Проблема решается, когда вы используете Filter вместо Include. Параметр фильтра вернет файл в правильном порядке с глубиной. (ИСПЫТАНО)

dir 'C:\Program Files\' -Filter *.txt  -Depth 1
1 голос
/ 03 марта 2020

В более старых версиях PowerShell не было никакой глубины, в этом случае выше также может быть

Get-ChildItem -Path "C:\DIRECTORY\*","C:\DIRECTORY\*\*"

Если это чисто для имен файлов, то

(Get-ChildItem -Path "c:\program files" -file -Depth 3 -Force -erroraction SilentlyContinue).FullName

Идентично древние трюки, например

(cmd.exe /c dir "c:\program files" /b /a-d /s)|foreach {if ($_.split("\").length -le 5){$_}}

Удивительно, что PowerShell даже быстрее, чем приведенная выше строка! Я помню, что несколько лет go это было не так, но я только что проверил, и это было в 3-4 раза быстрее

0 голосов
/ 03 марта 2020

Для дальнейшего разъяснения ответа Васифа Хасана Когда я просматривал официальную документацию для Get-ChildItem, там указано

При использовании параметра -Include, если вы не включите звездочку в путь, команда не возвращает никаких выходных данных.

Это означает, что Depth будет автоматически игнорироваться, поскольку поведение, требуемое для Include является рекурсивным. Далее некоторые подробности -Include раскрывают эти точки.

Если в команду добавлен параметр Recurse, конечная звездочка (*) в параметре Path является необязательной. Параметр Recurse получает элементы из каталога Path и его подкаталогов. Например, -Path C: \ Test \ -Recurse -Include * .txt

Таким образом, искомое поведение находится во флаге Filter для Get-ChildItem, который не требует каких-либо подстановочных знаков

Для меня флаг Depth с любым другим флагом, который принимает подстановочные знаки в пути, не имеет смысла, так как цель флага Depth состоит в ограничении глубины поиска в Элементы, в которых указание подстановочного знака исключает эту конкретную цель. Вы можете попробовать это, просто используя эту команду, и вы увидите, что параметр Depth не действует, если вы указали подстановочный знак в пути, например

Get-ChildItem -Path C:\DIRECTORY\* -Depth 1

и

Get-ChildItem -Path C:\DIRECTORY\* -Depth 2

собираются вернуть те же результаты.

Надеюсь, это поможет прояснить некоторые проблемы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...