在递归搜索中使用变量,并在复制文件后停止

时间:2015-02-12 14:32:39

标签: batch-file recursion xcopy

我有以下批处理脚本,它接收文件列表并递归遍历并尝试复制文件:

        for /f "usebackq delims=" %%x in (Files.txt) do 
    ( (for /R "\\network\Sites\" %%f in (%%x) do 
(echo F | xcopy /i "%%f" C:\Files\ )) )

上面的确有效,但是即使在复制文件之后它也会循环遍历所有子文件夹,这需要大约25分钟,并且考虑到需要复制的文件数量,这不是一个可行的解决方案。我已经更新了输入文件,以包含为每个文件更改的文件结构的其他部分,以限制需要搜索的文件夹数量,如下所示:

for /f "delims=, tokens=1,2" %%x in (new2.csv) do 
( (for /R "\\network\Sites\%%x\Analyzed\" %%f in (%%y) do 
(echo F | xcopy /i "%%f" C:\Files\ )) )

问题是它没有填充csv文件中的%%x变量,只是使用路径\\network\Sites\%x\Analyzed\运行命令,但%%y变量已正确填充文件名。

无论如何要填充它?是否有更好的方法来递归搜索文件并复制它而不是我上面所做的(使用for /r)?

此外,有没有办法让脚本在xcopy成功复制后继续下一个文件?

我一直在寻找类似的问题,但在我的案例中似乎没有一个解决方案。

编辑:根据请求包含更多信息。

我想解决的问题是我有一个需要从UNC路径复制的文件列表。问题是,通过主目录(\\network\Sites\)中的所有子文件夹进行递归并尝试复制文件的天真方法需要大约。由于要搜索的目录数量,每个文件25分钟,因为需要复制的文件数量使其成为不可行的解决方案。

files.txt只是一个文件名列表,其扩展名由换行符分隔,例如

123hsdfs.ext 4t5efrre.ext

在第二次尝试中,new2.csv是一种方法,我尝试在文件列表中提取预期目录的其他部分,以减少脚本必须搜索的子文件夹的数量。该文件将包含以下内容:

001,123hsdfs.ext 002,4t5efrre.ext

我尝试将001002放入for /r循环,但执行时变量未正确填充。我在搜索123hsdfs.ext时所期望的递归循环将使用它使用\\network\Sites\001\Analyzed\的根文件夹\\network\Sites\%x\Analyzed\

所以,我试图解决的问题有两部分:

1)当每个文件的部分目录可以更改时,如何减少搜索到的子文件夹的数量(理想情况下,只能在{{1}的每个子目录中的Analyzed目录中递归搜索例如,在\\network\Sites\\network\Sites\001\Analyzed等中搜索,因为使用\\network\Sites\002\Analyzed方法的工作要多得多吗?

2)如果成功复制当前文件,如何继续查看列表中的下一个文件,这样我就不必在文件夹中搜索它了?

3 个答案:

答案 0 :(得分:1)

for /f "usebackq delims=" %%x in (Files.txt) do (
 for /R "\\network\Sites\" %%f in (%%x) do (
   echo F | xcopy /i "%%f" C:\Files\ && (
     goto :break
   )
  ) 
)
:break

只打破外部循环使用子程序。内部循环仍然可以访问外部甚至包含在子程序或批处理文件中的标记:

for /f "usebackq delims=" %%x in (Files.txt) do (
   call :internal
)
exit /b 0

:internal
 for /R "\\network\Sites\" %%f in (%%x) do (
   echo F | xcopy /i "%%f" C:\Files\ && (
     goto :break
   )
  ) 
:break
exit /b 0

goto打破for上下文并用于终止其执行。

答案 1 :(得分:0)

您需要setlocal EnableDelayedExpansion;但是,为了使其正常工作,您需要常规变量来保存每个循环中的值:

@echo off
setlocal EnableDelayedExpansion
for /f "tokens=1,2 delims=," %%x in (new2.csv) do (
  set x=%%x
  for /R "\\network\Sites\!x!\Analyzed\" %%f in (%%y) do (
    set f=%%f
    xcopy /i "!f!" C:\Files\
  )
)

答案 2 :(得分:0)

@ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
:: remove variables starting $
FOR  /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="

FOR /f "delims=" %%a IN (q28480130.txt) DO SET "$%%a=Y"
FOR /r "%sourcedir%" %%a IN (*.*) DO (
 SET "left="
 FOR /f "delims==" %%w IN ('set $') DO IF /i "%%w"=="$%%~nxa" (
  ECHO found %%~fa
  SET "%%w="
  XCOPY /i "%%~fa" "%destdir%\" >nul
 ) ELSE (SET "left=Y")
 IF NOT DEFINED left GOTO done
)
echo these file not found
set $
:done
ECHO all done
DIR %destdir%

GOTO :EOF

这可能适合你。

您需要更改sourcedirdestdir的设置以适合您的具体情况。

我使用了一个名为q28480130.txt的文件,其中包含我的测试数据

123hsdfs.ext
4t5efrre.ext
gx112 juf.lgmm
pq72-99!.kut
ttyopd
$92k.opz

该过程首先清除从$开始的所有环境变量。

然后为文件中的每个文件名设置一个环境变量$filename

然后读取源目录,filename-by-filename并查看环境中$ filename是否为set。如果是,请从环境中清除它并复制文件(我将选项保留为相同并通过使用尾随echo来避免\

首先在每个循环中清除

left,然后设置环境中设置的“文件名”与找到的文件名之间是否存在不匹配(因为不匹配意味着文件尚未找到)。因此,如果leftfor..%%w完成时仍然未定义,那么刚刚找到并从环境中删除了最后一个$ filename,因此我们可以终止该过程。

如果找不到任何名称,那么这些名称将由for...%%a循环的常规出口列出。它们将以$为前缀。对于任何有兴趣的人来说,轻松处理并留下作为一个小练习。