在dos中为dir命令设置递归深度
Posted
技术标签:
【中文标题】在dos中为dir命令设置递归深度【英文标题】:How to set recursive depth for the Windows command DIR? 【发布时间】:2012-09-10 20:23:03 【问题描述】:我目前正在使用以下命令列出一些目录:
dir /b /s /AD > c:\temp\dir_list.txt
这几乎给了我我需要的清单。但是数据太多了,因为有些文件夹有很多子文件夹,我不想在我的列表中看到。
是否可以将命令的递归深度限制为 -let say- 3?
c:\dir_1\dir_2\dir_3\dir_foo
因此,如果我在 c:> 中执行上述示例中的命令,我不想看到 dir_foo 目录,而只想看到 dir_n 目录...
也许没有批处理/vb 脚本?
【问题讨论】:
相关; ***.com/questions/13249085/… 【参考方案1】:我确信可以编写一个列出 n 级目录的复杂命令。但是很难记住语法并且容易出错。每次您想要更改级别数时,它也需要更改。
最好使用简单的脚本。
5 年后编辑 - 实际上,自 Vista 以来就有一个简单的衬板可用。 See my new ROBOCOPY solution.
这是一个执行深度优先列表的批处理解决方案。 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
【讨论】:
好东西!效果很好。虽然有一个小“错误”。如果涉及到一个文件夹,则系统不允许访问,它会上一个目录并使用旧列表在那里工作。但我不在乎这个!不管怎么说,还是要谢谢你!这正是我想要的! @Sauer - 诊断错误的工作做得很好 :-) 我修复了代码以消除错误。 我们如何做到这一点,包括隐藏文件夹? @ChefGladiator - 我认为这可行,但未经测试:将简单的FOR /D
行更改为 FOR /F "EOL=: DELIMS=" %%F IN ('DIR /A:D') DO (
。或者更好的是,在我的另一个答案中使用ROBOCOPY
技术,因为它默认读取系统文件。
@dbenham 启发了谢谢你......正确的咒语是'DIR /B /S /A:HD'
- 它将仅列出当前目录下方的隐藏目录。【参考方案2】:
经过这么长时间(5 年),我刚刚偶然发现了一个简单的命令行,它一直可用。 ROBOCOPY
自 Vista 以来一直是标准的 Windows 实用程序,可通过 Windows 资源工具包在 XP 中使用。
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
但是输入命令变得有点笨拙。将这种技术合并到以根路径和级别作为参数的实用程序批处理文件中应该很容易。如果将命令放在批处理脚本中,则必须记住将百分比加倍。
【讨论】:
您好! +1 因为我喜欢 robocopy 和您的奉献精神。但我更喜欢使用您的第一个解决方案(它更具表现力)【参考方案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 ...
可以设置缩进字符
【讨论】:
以上是关于在dos中为dir命令设置递归深度的主要内容,如果未能解决你的问题,请参考以下文章