通过批处理脚本构建目录列表。需要排除一些目录。怎么样?

时间:2014-04-07 04:22:23

标签: cmd dir

我使用数十万个文件夹/文件,其中大多数都有某些日志文件。手动浏览文件夹以获取日志需要花费大量时间,因此我一直在使用脚本来执行此操作。

它是一个2人。第一部分在一夜之间运行以解析所有目录(它们每天都会更改,并且会经常添加新日志,因此我会每晚对所有内容进行索引以使索引保持最新状态。)

这第一部分是自动的,我从不触摸它,它只是每晚运行。输出转到txt文件,在执行第二个脚本时使用。

我在第二个脚本中放入了我正在寻找的日志的关键字。此脚本依赖于第一个脚本的txt输出来快速定位文件并将其下拉。

(我这样做的原因是因为它有5秒的任务来解析寻找文件的300,000行文本文件,以及15-30分钟的搜索工作(索引所有网络共享)。我可以在5秒钟而不是30多分钟内获取我的日志。

在上周之前,日志目录包含大约5000个文件和文件夹。上周末,IT切换到了一个新系统,它现在包含超过500,000个文件和文件夹。他们抛弃了档案,还有一堆我不需要的其他档案。

用于在大约10-15分钟内对其进行索引的第一个脚本(它的网络共享,实际上是4个网络共享),一夜之间没问题。虽然现在这是一个4小时以上的壮举。我需要能够在索引编制期间排除某些目录,从而将500,000个文件/文件夹数量减少到5,000以下。

我一直用这个命令来索引:

dir /b /-d /-p /s /A:-D > C:\output.txt

我需要让索引跳过包含单词“Common”或“Old”的任何目录,也可能跳过其他目录。目标是通过不进入这些目录来节省时间。

我尝试使用PowerShell来做这件事,但我对此一无所知。

我需要输出格式如下:

C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\dbInstaller.exe
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\DisplayDriver.nvi
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\DisplayDriverExt.dll
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\license.txt
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\mcu.ex_
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvae.inf
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvak.inf
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvapi.dl_
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvapi64.dl_
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvcompiler.dl_
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvcompiler32.dl_
C:\NVIDIA\DisplayDriver\GeForce332.21Driver\Display.Driver\nvcplsetupeng.exe

谢谢!

2 个答案:

答案 0 :(得分:0)

@ECHO OFF
SETLOCAL
SET "sourcedir=."
(
FOR /f "delims=" %%a IN (
  'dir /b /s /ad "%sourcedir%\*" ^|findstr /v /i /l /g:q22903564.txt'
  ) DO ( FOR /f "delims=" %%b IN ('dir /b /a-d "%%a" 2^>nul') DO ECHO(%%a\%%b
)
)>newfile.txt

GOTO :EOF

我使用了一个名为q22903564.txt的文件,其中包含用于测试的排除字词。 生成newfile.txt。

当然,sourcedirq22903564.txtnewfile.txt的选择都在你的法庭上......

@ECHO OFF
SETLOCAL
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")

SET "sourcedir=."

:: get a dir listing from the root
(
FOR /f "delims=" %%a IN (
 'dir /b /ad "%sourcedir%\*" ^|findstr /v /i /l /g:q22903564.txt'
 ) DO (ECHO("%%~fa")
)>"%tempfile%b"

:again

(
FOR /f "usebackqdelims=" %%a IN ("%tempfile%b") DO (
 FOR /f "delims=" %%b IN (
 'dir /b /ad "%%~a\*" ^|findstr /v /i /l /g:q22903564.txt'
 ) DO FOR /f "delims=" %%c IN ('ECHO("%%~a\%%b"^|findstr /x /v /i /l /g:"%tempfile%b"') DO ECHO "%%~c"
)
)>"%tempfile%c"

FOR %%a IN ("%tempfile%c") DO SET /a sizec=%%~za
IF %sizec% gtr 0 TYPE "%tempfile%c">>"%tempfile%b"&GOTO again

(
FOR /f "usebackqdelims=" %%a IN ("%tempfile%b") DO (
 FOR /f "delims=" %%b IN (
 'dir /b /a-d "%%~a\*" 2^>nul'
 ) DO ECHO(%%~a\%%b
)
)>newfile.txt

DEL "%tempfile%*"

GOTO :eof

嗯 - 需要向你收取额外的费用,据一些人说,这是不可能的。


@ECHO OFF
SETLOCAL
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")

SET "sourcedir=."

:: get a dir listing from the root
(
FOR /f "delims=" %%a IN (
 'dir /b /ad "%sourcedir%\*" ^|findstr /v /i /l /g:q22903564.txt'
 ) DO (ECHO("%%~fa")
)>"%tempfile%b"

SET /a sizec=0

:again
SET "skipcnt=usebackq"
IF %sizec% gtr 0 (
 FOR /f %%a IN ('type "%tempfile%b" ^|find /c /v ""') DO SET "skipcnt=usebackqskip=%%a"
 TYPE "%tempfile%c">>"%tempfile%b"
)

(
FOR /f "%skipcnt%delims=" %%a IN ("%tempfile%b") DO (
 FOR /f "delims=" %%b IN (
 'dir /b /ad "%%~a\*" ^|findstr /v /i /l /g:q22903564.txt'
 ) DO FOR /f "delims=" %%c IN ('ECHO("%%~a\%%b"^|findstr /x /v /i /l /g:"%tempfile%b"') DO ECHO "%%~c"
)
)>"%tempfile%c"

FOR %%a IN ("%tempfile%c") DO SET /a sizec=%%~za
IF %sizec% gtr 0 GOTO again

(
FOR /f "usebackqdelims=" %%a IN ("%tempfile%b") DO (
 FOR /f "delims=" %%b IN (
 'dir /b /a-d "%%~a\*" 2^>nul'
 ) DO ECHO(%%~a\%%b
)
)>newfile.txt

DEL "%tempfile%*"
GOTO :eof

第三次是魅力。此版本计算出已经处理了多少行目录,并在重新处理连接列表b和c时跳过这些行。 IOW,它只处理添加内容。

在打字时,我意识到还有一点简化......不得不等早茶......不过......


@ECHO OFF
SETLOCAL
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")

SET "sourcedir=."

:: get a dir listing from the root
(
FOR /f "delims=" %%a IN (
 'dir /b /ad "%sourcedir%\*" ^|findstr /v /i /l /g:q22903564.txt'
 ) DO ECHO(%%~fa
)>"%tempfile%c"

SET /a sizec=0

:again
SET "skipcnt=usebackq"
IF %sizec% neq 0 FOR /f %%a IN ('type "%tempfile%b" ^|find /c /v ""') DO SET "skipcnt=usebackqskip=%%a"
TYPE "%tempfile%c">>"%tempfile%b"

(
FOR /f "%skipcnt%delims=" %%a IN ("%tempfile%b") DO (
 FOR /f "delims=" %%b IN (
 'dir /b /ad "%%a\*" ^|findstr /v /i /l /g:q22903564.txt'
 ) DO ECHO(%%a\%%b
)
)>"%tempfile%c"

FOR %%a IN ("%tempfile%c") DO SET /a sizec=%%~za
IF %sizec% gtr 0 GOTO again

(
FOR /f "usebackqdelims=" %%a IN ("%tempfile%b") DO (
 FOR /f "delims=" %%b IN (
 'dir /b /a-d "%%a\*" 2^>nul'
 ) DO ECHO(%%a\%%b
)
)>newfile.txt

DEL "%tempfile%*"
GOTO :EOF

这次肯定! (没有狮子的吼声)

我意识到对原始tempfileb内容的重新过滤是多余的 - 并且删除这意味着可以缩减用于克服尴尬角色的引用制度。然后实际上原始文件是一个空的tempfileb的原始添加(tempfilec),所以 - 一点重组和挥手(因为'skip = 0'无效),结果是以后扫描的唯一目录是在最后一次迭代中添加了thos,优化了目录扫描方法。

现在结果是结果列表将是\ a \,\ b \,\ c \,\ a \ a1 \,\ b \ b1 \等等 - 但是简单的sort如果需要,结果应该照顾好。

答案 1 :(得分:0)

这可能有所帮助:它会排除第3行中您看到"Common Old"

的条款

它会创建文件夹列表,过滤掉排除的字词,然后使用剩余的文件夹创建列表。

如果您只想要*.log *.txt个文件等,那么可以再次提高效率 - 否则请删除第7行批处理文件中的*.log *.txt条款

@echo off
dir /b /ad /s /-p > "C:\output.txt"
findstr /v /i "Common Old" "C:\output.txt" >"C:\output2.txt"
del "C:\output.txt"

for /f "usebackq delims=" %%a in ("C:\output2.txt") do (
   pushd "%%a"
      for /f "delims=" %%b in ('dir *.log *.txt /b /-p /a-d') do >>"C:\output.txt" echo(%%a\%%b
   popd
)