0

我有一个包含数千个文件的目录。

有没有办法只获取 x 文件?(最好用于批处理文件)

但是(这就是为什么它不是我已经找到答案的相同问题之一)

无需“dir”命令处理整个目录内容或使用“for”循环。

尽管“for”循环(即 for %%a in ( .txt) do [something])与计数器相结合会起作用,但这样做需要相当长的时间。我只能假设“for”循环中的文件“集”(即(.txt))首先获取整个内容并对其进行迭代。

如果我可以在 x 返回值之后停止“dir”命令,那会很好,但我想不出办法来做到这一点(甚至可能还是我只是回答我的问题但缺乏编码的知识它?)。

提前致谢。

4

1 回答 1

4

您对 FOR 循环有误。只要您不使用 /R 选项,它就非常快。(我在 XP、Vista 和 Windows 7 上测试过)

我创建了一个包含 20,000 个文件的测试目录并运行以下脚本 - 它打印出第 10 个文件并在眨眼间完成:

@echo off
set n=0
for %%F in (*) do (
  echo %%F
  set /a "n+=1, 1/(10-n)" 2>nul || goto :break
)
:break

我通过故意除以 0 来检测何时达到 10 个文件以生成错误。我本可以使用延迟扩展并测试计数器的值,但%%F如果文件名包含!字符并且启用了延迟扩展,则无法正确打印。

因此,与您的看法相反,一个简单的 FOR 不会迭代循环之前收集所有值。

您可能对 FOR /F 变体感到困惑:for /f "delims=" %%F in ('dir /b /a-d *') do .... 在这种情况下,DIR 命令在其自己的 shell 中执行,并且在任何 FOR 迭代之前获得整个结果集。

使用 FOR 解决方案需要注意的一件事 - FOR /R 选项似乎有可能减慢速度。我修改了上面的脚本以使用 /R 选项,然后在我的C:\根目录上运行它。它很快打印了它找到的前 10 个文件,但随后似乎挂了很长时间,然后终于完成了。我不知道如何证明这一点,但我认为 FOR 循环正在浪费时间迭代我C:驱动器上的所有目录,即使它没有对它们做任何事情。

编辑

我刚刚阅读了 PA. 对原始问题的评论。他有一个很好的观点——在某种程度上,FOR 和 DIR 都必须读取整个目录,以便执行隐式排序操作以正确顺序返回文件。但是,他也指出这是在非常低的水平上完成的。我的观点是 FOR 命令在开始迭代之前不需要等待所有值都返回(或为此而跳出循环)。

编辑 2 FOR /F 行为可能是福也可能是祸。对于这个应用程序,这是一个诅咒。但有时您在处理目录时会更改目录的内容。FOR /F 变体可防止您看到命令启动后发生的任何更改。简单的 FOR 命令有时可以在开始迭代后看到目录内容的变化。

FOR 命令以块的形式缓冲迭代 - 它会迭代它在缓冲区中的所有文件,但是当缓冲区为空并返回操作系统以获取下一个块时,它可以看到目录发生的更改. 这是一个演示该行为的测试脚本:

@echo off
md myTemp
for /l %%N in (1001 1 6000) do echo a>myTemp\%%N.txt
for /f %%N in ('dir /b myTemp\* ^| find /c /v ""') do Echo Starting with %%N files
set cnt=0
(
  for %%F in (myTemp\*) do (
    echo %%F
    del /q myTemp\* 2>nul
    set /a cnt+=1
  )
)> test_for.out
echo Only %cnt% files were listed by FOR
echo(

for /l %%N in (1001 1 6000) do echo a>myTemp\%%N.txt
for /f %%N in ('dir /b myTemp\* ^| find /c /v ""') do Echo Starting with %%N files
set cnt=0
(
  for /f %%F in ('dir /b /a-d myTemp\*') do (
    echo %%F
    del /q myTemp\* 2>nul
    set /a cnt+=1
  )
)> test_for_f.out
echo All %cnt% files were listed by FOR /F

rd myTemp

结果如下:

Starting with 5000 files
Only 743 files were listed by FOR

Starting with 5000 files
All 5000 files were listed by FOR /F

两个循环都从 5000 个文件开始,并在第一次迭代后删除所有文件。FOR /F 仍会处理启动时目录中的所有 5000 个文件名。FOR 仅处理适合缓冲区的 743 个文件名。

注意:我在 Windows 7 上获得了上述结果。我还在 Vista 和 XP 上进行了测试,除了在 FOR 循环中仅列出 35 个文件而不是 743 个文件之外,结果都相同。

于 2012-07-06T18:15:38.123 回答