Приведенное ниже решение, основанное на вашем собственном, предполагает, что ваше намерение состоит в том, чтобы найти те дочерние каталоги, поддеревья которых превышают заданную глубину .
Если вы хотите найти все пути к каталогам, которые находятся на заданной глубине или глубже , см. Нижний раздел.
Ваш подход не может этого достичь, потому что он находит каталоги только на заданной глубине, а не ниже.
Ваш умный подход, основанный на шаблонах, должен работать в принципе, но:
(а) это может быть значительно упрощено.
(b) требуется дополнительная работа, чтобы ограничить вывод отдельным списком тех дочерних папок, поддеревья которых слишком глубоки.
(a) Оптимизация вашего подхода:
$Depth = 3
$Path = '.'
$Levels = '/*' * $Depth
Get-ChildItem -Directory $Path/$Levels
Как и в вашем собственном подходе, '/*' * $Depth
динамически создает групповое выражение уровня нескольких каталогов (например, /*/*
для $Depth
из 2
), которое может быть добавлено к входу $Path
соответствовать только путям на этом уровне.
Переключатель -Directory
(PSv3 +) ограничивает соответствие только для каталогов.
(b) Ограничение вывода отдельным набором папок верхнего уровня со слишком глубокими поддеревьями:
$Depth = 3
$Path = '.'
$Levels = '/*' * $Depth
Get-ChildItem -Directory $Path/$Levels |
ForEach-Object { ($_.FullName -split '[\\/]')[-$Depth] } |
Select-Object -Unique
Примечание. Разделение по [/\\]
, то есть по /
или \
, делает решение работоспособным и на Unix-подобных платформах (PowerShell Core ); в Windows достаточно -split '\\'
(через экранированный \
).
При использовании вашей иерархии папок с примерами приведенное выше даст:
folder1
folder2
Если вы хотите вместо полные пути , добавьте
| Convert-Path -LiteralPath { "$Path/$_" }
.
Если вы хотите объекты каталогов ([System.IO.DirectoryInfo]
) вместо этого, добавьте
| Get-Item -LiteralPath { "$Path/$_" }
.
Необязательное чтение: получение папок до, на или за определенной глубиной:
Примечание:
Несмотря на то, что указанные ниже решения предназначены для папок (каталогов), вы также можете включить файлов , просто пропустив -Directory
, или целевые файлы только заменив -Directory
с -File
.
Для простоты команды неявно ориентированы на текущий каталог.
At-a- только для заданной глубины логика:
Это та же логика, что и в приведенном выше решении; следующий код перечисляет папки на глубине 2 только , то есть на уровне внука (дочерние каталоги дочерних каталогов) - обратите внимание, что, в отличие от Get-ChildItem -Depth
, подсчет глубины начинается с 1
, то есть 1
относится к дочерним каталогам:
$depth = 2 # grandchild directories only
Get-ChildItem -Directory -Path ('*/' * $depth)
Чтобы вывести полные пути , заключите команду Get-ChildItem
в (...).FullName
или перенаправьте ее на Select-Object -ExpandProperty FullName
.
Для вывода относительных путей (например, folder1/test1/test/testsub
) требуется дополнительная работа, поскольку добавление -Name
будет не работать в этом случае, как ожидается (это выведет только каталог names ):
$depth = 2 # grandchild directories
# Calculate the length of the path prefix for determining relative paths.
# (Using the current dir ($PWD) as the reference path here.)
$PrefixLen = (Convert-Path -LiteralPath $PWD).Length + 1
$Levels = '/*' * $Depth
Get-ChildItem -Directory -Path ('*/' * $depth) |
ForEach-Object { $_.FullName.Substring($PrefixLen) }
До логика заданной глубины:
Параметр PSv5 + -Depth
ограничивает глубину рекурсии Get-ChildItem
, т. Е. Он находит элементы только до указанной глубины, но учтите, что это глубина 0
, а не 1
, представляющая непосредственных детей .
Обратите внимание, что использование -Depth
подразумевает -Recurse
, хотя вы также можете указать и последнее.
Например, для перечисления дочерних папок и папок внуков (2 уровня) в текущем каталоге используйте:
$depth = 2 # child and grandchild directories
Get-ChildItem -Directory -Depth ($depth - 1)
Чтобы вывести полные пути , заключите команду Get-ChildItem
в (...).FullName
или перенаправьте ее на Select-Object -ExpandProperty FullName
.
Для вывода относительных путей просто добавьте переключатель -Name
к вызову Get-ChildItem
.
At-a- заданная глубина-или-глубже логика:
Ограничение результатов элементами на уровнях, превышающих или равных заданной глубине, требует специального решения:
$depth = 2 # grandchild directories and below
Get-ChildItem -Directory -Name -Recurse |
Where-Object { ($_ -split '[/\\]').Count -ge 2 } |
Get-Item -LiteralPath { "$PWD/$_" }
Если ваш входной путь не является (подразумеваемым) текущим направлением, замените этот путь на $PWD
.
Для вывода полных путей , замените Get-Item
на Convert-Path
.
Для вывода относительных путей , просто пропустите вызов Get-Item
.