Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 批量迭代大量文件_Batch File_For Loop - Fatal编程技术网

Batch file 批量迭代大量文件

Batch file 批量迭代大量文件,batch-file,for-loop,Batch File,For Loop,我编写了一个简短的批处理脚本,它遍历目录及其子目录的文件。总共有一百多万个文件。如果我将批处理用于较小数量的文件和目录,则批处理可以正常工作。但如果我试着用它来解决所有问题,它似乎永远不会停止工作。 我的印象是,在获得输出之前,脚本需要“检查”每个文件。所以我的问题是:如果批处理工作正常,有没有办法更快地完成这项工作,或者至少进行测试 下面是我的示例代码: FOR /F "delims=*" %%i IN ('dir /s /b *.txt') do echo "test" 提前谢谢你 性能:

我编写了一个简短的批处理脚本,它遍历目录及其子目录的文件。总共有一百多万个文件。如果我将批处理用于较小数量的文件和目录,则批处理可以正常工作。但如果我试着用它来解决所有问题,它似乎永远不会停止工作。 我的印象是,在获得输出之前,脚本需要“检查”每个文件。所以我的问题是:如果批处理工作正常,有没有办法更快地完成这项工作,或者至少进行测试

下面是我的示例代码:

FOR /F "delims=*" %%i IN ('dir /s /b *.txt') do echo "test"

提前谢谢你

性能:迭代一个目录及其所有子目录中的所有文件不是很快。我不确定,但我认为批处理必须直接检查硬盘上的每个目录。访问硬盘总是很慢。如果您想加快速度,可以使用一个批处理将目录拆分为更小的批处理,并将这些批处理传递给执行实际工作的其他脚本

进度:我不知道语法方面的确切答案,但是如果您使用echo命令显示正在迭代的当前文件,您可以看到批处理是否正在运行。

尝试如下:

@echo off
FOR /F "delims=*" %%i IN ('dir /s /b *.txt') do (
cls    
echo treating : [%%i]
)
echo Done.....

编辑以包含评论中讨论的信息

这个问题最初的答案是

for /r "c:\startingPoint" %%a in (*.txt) do echo %%~fa
它将递归地处理文件,因为它们位于磁盘中,没有等待或暂停,或者至少没有不必要的暂停(当然需要找到第一个文件)

anwswer和原始代码之间有什么区别

FOR /F "delims=*" %%i IN ('dir /s /b *.txt') do echo "test"
在这个问题上

通常,
for/f
用于迭代一组行而不是一组文件,为每一行执行
for
命令体中的代码。命令的
子句中的
定义从“where”检索行集

该“where”可以是要读取的磁盘上的文件,也可以是要执行的命令或命令集,其输出将被处理。在这两种情况下,在开始处理之前,将完全检索所有数据。直到所有数据都在内存缓冲区中,才会执行
for
命令体中的代码

这就是区别所在

读取磁盘中的文件时,
for/f
获取文件的大小,并分配一个足够大的内存缓冲区,以便在内存中容纳完整的文件,将文件读入缓冲区并开始处理缓冲区(当然,您不能使用
for/f
来处理大于可用内存的文件)

但是当/f的
处理一个命令时,它会分配一个起始缓冲区,将执行命令的stdout流中的数据追加到该缓冲区中,当缓冲区已满时,会分配一个新的更大的缓冲区,将旧缓冲区中的数据复制到新缓冲区,并丢弃旧缓冲区。在新缓冲区的指定点检索新数据。每次缓冲区满了,这个过程都会重复。缓冲区少量增加的事实加剧了这种情况

因此,当命令生成的数据非常大时,会进行大量内存分配、复制、释放。这需要时间。对于大数据,需要花费大量时间

总之,如果使用/f的
for
来处理命令的输出,并且要处理的数据很大,则需要的处理时间将以指数方式增加


如何避免呢?问题(在这种情况下)是从命令中检索数据,而不是处理数据。因此,当数据量非常大时,最好执行命令将输出重定向到临时文件,然后使用
for/f
处理文件,而不是通常的
for/f%%a in('command')..
语法。数据的生成将需要相同的时间,但数据处理延迟的差异可能从几小时到几秒或几分钟。

由于不清楚您实际要做的是什么,并且一行标称代码没有任何影响,因此很难做出除一般性评论之外的任何评论

如果你把你的batchette换成

FOR /F "delims=*" %%i IN ('dir /s /b %1*.txt') do echo "test"
并用

for %%a in (a b c d...x y z 0 1..9) do start yourlittlabatch %%a
(我假设您会意识到d..x意味着所有的字符d到x-我不会为您列出它们-并且您还需要在列表中包含任何正在使用的非字母数字首字母字符)

然后您将得到36个并行进程,每个进程处理目标结构的一部分。如果您有一台多处理器机器,这应该会更快——显然,我还假设文件名的初始字符有一定的规则分布


您提供的信息越多,我们所做的假设就越少……

For/f
中存在一个
错误,当它必须处理许多文件时,长文件名会使情况变得更糟(解析为文件名的总数据是最重要的因素)。它只需解析列表,就可以等待一个多小时

解决方案是在文件中使用dir命令,然后在for/f命令中使用该文件

dir /s /b /a-d *.txt >file.tmp

FOR /F "delims=*" %%i IN (file.tmp) do echo "test"

非常感谢,这正是我想要的。还有一个问题:你为什么用%%~fa而不是%%a?@Daniel,只是为了确定我得到了什么。添加到
%%a
可替换参数的
~f
返回文件的完整路径。根据
for
命令中使用的确切语法/选项,它有时返回完整路径,有时仅返回文件名。如果以后我更改
for
中的选项,请明确说明我希望减少错误的内容。这实际上是
for/f
中的一个错误,因为它解析大型列表。如果文件名足够长的话,比如500000个文件,那么它将在比解析一个文件名列表所需的时间更长的时间内处于静止状态,并且什么也不做。一旦触发该漏洞,更多文件名的时间延迟也是指数级的,并且可以被删除