【问题标题】:Findstr too slow on UNC batch scriptFindstr 在 UNC 批处理脚本上太慢了
【发布时间】:2021-03-03 13:28:39
【问题描述】:

我正在运行一个遍历网络文件夹并保存找到的文件的脚本,但是运行时间太长。我已经尝试将 findstr 隔离到一个文件夹中并且它在正常的时间运行,所以我认为它与 FOR 循环有关。

@echo off

setlocal

set SERVERS=server1 server2 server3 server4

cls
echo Type below the query parameters:
set /p year=Year (4 digits): 
set /p month=Month (2 digits): 
set /p day=Day (2 digits): 
set /p query=Query string: 
cls
echo Results:
del /F /Q "C:\Users\%USERNAME%\Desktop\found_files\*" 2>nul
if not exist "C:\Users\%USERNAME%\Desktop\found_files" mkdir "C:\Users\%USERNAME%\Desktop\found_files"
for /f "tokens=*" %%a in ('for %%i in ^(%SERVERS%^) do @findstr /S /I /M /C:"%query%" "\\%%i\folder_structure\*%year%-%month%-%day%*.xml"') do copy /Y "%%a" "C:\Users\%USERNAME%\Desktop\found_files" >nul & echo %%a & set found=1
echo.
if "%found%"=="1" (
    echo File^(s^) saved successfully!
) else (
    echo No files found!
)
echo.
pause
if "%found%"=="1" explorer C:\Users\%USERNAME%\Desktop\found_files

【问题讨论】:

  • 嵌套for 循环会减慢您的代码速度,但不一定达到您所经历的程度。我怀疑瓶颈来自访问 UNC 路径上的文件,临时将该路径安装为网络驱动器会加快速度,但我无法测试。
  • 记住重定向和使用 echo 在每次迭代的基础上输出结果会大大减慢速度。
  • @T3RR0R - 在每次迭代中重定向到 nul 应该不会产生太大影响,因为它永远不会花费时间来打开文件。我在一个紧密的循环中测试了 10000 个>nul 重定向,只用了 1.6 秒,而在循环外重定向一次只用了 1.2 秒。这是一个区别,但可能无关紧要。使用>>"file" 之类的东西时,迭代重定向变得非常慢,因为它必须重新打开文件并将文件重新定位到每次迭代的末尾。
  • @SomethingDark - 我一直认为将网络驱动器映射到 UNC 路径只不过是一种方便,或者是一种将路径与不理解 UNC 路径的命令一起使用的方法。我怀疑它会节省任何处理时间。但我想在尝试之前我们不会知道。映射 UNC 路径的最简单方法是使用 PUSHD

标签: for-loop batch-file findstr unc


【解决方案1】:

您的脚本已经优化得很好。我不认为你可以做很多事情来加快速度。

我怀疑您的问题是 FINDSTR 正在您的本地计算机上运行,​​它必须扫描所有 UNC 路径上的文件(几乎肯定不是本地的)。这意味着每个文件的全部内容都必须通过您的网络传输。如果你的系统和我工作的地方一样,那可能是一场噩梦。我们的网络驱动器性能很差(比本地驱动器慢 100 倍以上)!

Squashman(和SomethingDark)有点担心您的外部FOR /F 执行嵌套的FOR 语句。但我相信这是最有效的方法。当FOR /F 迭代命令输出时,它必须启动一个新进程来执行命令。您当前的脚本只需要一个子进程。

更“传统”的方法是将%SERVERS% 迭代移到内部循环之外,如下所示:

for %%i in (%SERVERS%) do for /f "tokens=*" %%a in (
  'findstr /S /I /M /C:"%query%" "\\%%i\folder_structure\*%year%-%month%-%day%*.xml"'
) do copy /Y "%%a" "C:\Users\%USERNAME%\Desktop\found_files" >nul & echo %%a & set found=1

但这实际上效率较低,因为它必须为%SERVERS% 中的每个 UNC 路径启动一个新的子进程。话虽如此,与通过网络传输文件内容的实际瓶颈相比,我认为差异并不显着。

为了显示 1 个与 100 个子流程的影响,我对以下逻辑等效(但无意义)的命令进行了快速比较:

for /f "delims=" %%F in (
  'for /l %%N in ^(1 1 100^) do @findstr /m "^" *'
) do echo %%F>nul
:: This took 39 seconds on my machine

for /l %%N in (1 1 100) do for /f %%F in (
  'findstr /m "^" *'
) do echo %%F>nul
:: This took 60.9 seconds on my machine

【讨论】:

  • 您的示例确实有道理,但我也想知道使用 FINDSTR /S 是否比使用 FOR /R 先迭代文件然后使用 findfindstr 更慢跨度>
  • @Squashman - 如果有的话,我认为让FINDSTR 导航树会更快,因为启动外部命令存在开销。虽然FINDSTR /S 可能应该避免,因为如果在驱动器上启用短文件名,可能会导致它丢失文件。
  • 我同意你的观点,一定是网络限制和文件数量。我相信我将不得不寻找其他方法来搜索它们,如果您有任何建议我很乐意接受,谢谢您的详尽解释:)
  • @GabrielVicente - 不仅仅是文件的数量,还有每个文件的大小。我相信FINDSTR /M 足够聪明,一旦找到匹配项就会短路。但是如果没有匹配,那么它必须搜索整个文件。我忘了提到通过网络复制匹配的文件也需要时间。
【解决方案2】:
@echo off

set SERVERS=server1,server2,server3,server4

cls
echo Type below the query parameters:

:: Type echo %date% on command prompt if its returns the current date dd/mm/yyyy format, you can load the variables using a substring:

set year=%date:~6,4%
set month=%date:~3,2%
set day=%date:~0,2%

set /p query=Query string: 

:: set counter for files founded
set found=0

cls
echo Results:

if not exist "C:\Users\%USERNAME%\Desktop\found_files" (mkdir "C:\Users\%USERNAME%\Desktop\found_files") else (del /F /Q "C:\Users\%USERNAME%\Desktop\found_files\*" 2>nul)

for /f %%i in (%SERVERS%) do ('@find /i /c "%query%" "\\%%i\folder_structure\*%year%-%month%-%day%*.xml"') do (
    
    if "%%i"=="1" (set /a found=%found%+1 && copy /Y "\\%%i\folder_structure\*%year%-%month%-%day%*.xml" "C:\Users\%USERNAME%\Desktop\found_files" >nul && echo File^(s^) saved successfully! & echo.) else (echo No files found!)

)
echo.
pause
if %found% gtr 0 (explorer C:\Users\%USERNAME%\Desktop\found_files)

【讨论】:

  • 请不要写非英文的帖子。 SO 是一个只有英文的网站。
  • @T3RR0R 我不想听起来粗鲁,但如果字符串需要转义,我会抓住,我相信 Heitor 提供的 FOR 循环有点错误 :) 不用担心,很多人帮助,我们会尽快解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
相关资源
最近更新 更多