Установить рекурсивную глубину для команды dir в dos

В настоящее время я использую следующую команду для перечисления некоторых каталогов:

dir /b /s /AD > c:\temp\dir_list.txt

Это дает мне почти список, который мне нужен. Но это слишком много данных, потому что в некоторых папках очень много подпапок, которые я не хочу видеть в моем списке.

Возможно ли ограничить глубину рекурсии команды на -lets say-3?

c:\dir_1\dir_2\dir_3\dir_foo

Итак, если я выполняю команду в приведенном выше примере в c: > , я не хочу видеть каталог dir_foo, но только dir_n...

Возможно, без пакета /vb - script?

Ответ 1

Я уверен, что можно написать сложную команду, которая будет перечислять n уровней каталогов. Но было бы трудно вспомнить синтаксис и склонность к ошибкам. Он также должен будет меняться каждый раз, когда вы хотите изменить количество уровней.

Гораздо лучше использовать простой script.

РЕДАКТИРОВАТЬ 5 лет спустя. На самом деле есть простой один лайнер, доступный с Vista. Посмотрите мое новое решение ROBOCOPY.

Вот пакетное решение, которое выполняет первый ввод глубины. Команда DIR/S выполняет первый листинг, но я предпочитаю этот формат глубины.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1

:procFolder
pushd %1 2>nul || exit /b
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do (
    echo %%~fF
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

Первая версия с шириной почти одинакова, за исключением того, что она требует дополнительного цикла FOR.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1

:procFolder
pushd %1 2>nul || exit /b
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do echo %%~fF
  for /d %%F in (*) do (
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

Оба сценария ожидают два аргумента:

arg1 = путь к корневому каталогу, который будет указан

arg2 = количество отображаемых уровней.

Итак, чтобы отобразить 3 уровня текущего каталога, вы можете использовать

listDirs.bat . 3

Чтобы отобразить 5 уровней в разных каталогах, вы можете использовать

listDirs.bat "d:\my folder\" 5

Ответ 2

После всего этого времени (5 лет), и теперь я просто спотыкаюсь о простой командной строке с одним лайнером, который был доступен все время. ROBOCOPY была стандартной утилитой Windows с Vista и доступна для XP через комплект ресурсов Windows.

robocopy . . /l /s /njh /njs /ns /lev:4 >c:\temp\dir_list.txt

Описание

    /L :: List only - don't copy, timestamp or delete any files.
    /S :: copy Subdirectories, but not empty ones.
  /NJH :: No Job Header.
  /NJS :: No Job Summary.
   /NS :: No Size - don't log file sizes.
/LEV:n :: only copy the top n LEVels of the source directory tree.

Параметр /lev:n включает в себя корень в подсчете, и вы хотите 3 уровня подкаталога, поэтому я добавил 1 к значению.

Обработка далее

Выход не идеален в том, что корневая папка включена в выход, и каждый путь содержит пробелы с фиксированной шириной. Вы можете легко устранить корневой путь, а также ведущие пробелы с FOR /F.

(for /f "skip=2 tokens=*" %A in ('robocopy . . /l /s /njh /njs /ns /lev:4') do @echo %A) >c:\temp\dir_list.txt

Выход ROBOCOPY включает в себя начальную пустую строку, поэтому skip должен быть 2 вместо 1.

Каждый путь заканчивается на \. Мне нравится эта функция, потому что очевидно, что мы перечисляем папки, а не файлы. Если вы действительно хотите исключить конечный \, вы можете добавить дополнительный FOR.

(for /f "skip=2 tokens=*" %A in ('robocopy . . /l /s /njh /njs /ns /lev:4') do @for %B in ("%A.") do @echo %~fB) >c:\temp\dir_list.txt

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

Ответ 3

Вот решение, основанное на первом решении по листингу @dbenham,
и позволяет устанавливать минимальный уровень.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1
set minLevel=%3
if not defined minLevel set minLevel=0

:procFolder
pushd %1 2>nul || exit /b
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do (
    if %currentLevel% geq %minLevel% echo %%~FF
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

Чтобы установить минимальный уровень, просто укажите его как третий параметр.
Например: для перехода с уровня 2 на уровень 5 вы можете использовать

listDirs.bat target_path 5 2

В качестве альтернативы вы можете перечислить с базового уровня, оставив этот параметр пустым

listDirs.bat target_path 5

Ответ 4

Это немного улучшает решение dbenham (и elady). Он отступает в соответствии с глубиной. Это значительно повышает читаемость.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1
set minLevel=%3
if not defined minLevel set minLevel=0

:procFolder
pushd %1 2>nul || exit /b
set "indent=."
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do (
    for /l %%i in (1,1,%currentLevel%) do echo|set /p=%indent%
    if %currentLevel% geq %minLevel% echo %%~fF
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

Можно указать символ отступа в set "indent ...