批处理文件:从多个目录中复制特定扩展名的文件到一个目录

55

我是新手,请耐心等待...

我正在尝试使用批处理文件将散布在一个主目录的多个子目录中的所有.doc文件复制到另一个目录中。我已经成功地使用以下命令获取了这些目录中我想要复制的所有文件(有数百个)的文件列表filelist.txt:

"C:\Main directory\sub directory" dir /b /s *.doc > "C:\Main directory\sub directory\filelist.txt"

我应该使用什么脚本将它们复制到一个目录中?我能否使用一些代码从filelist.txt中获取这些文件名并将它们复制过去?

为了参考,我看了下面的问题,因为它似乎正在做我想做的事情,但对我没有用。

Using xcopy to copy files from several directories to one directory

此外,我真的很想理解这个概念,请为我分解代码以告诉我每个项目都是做什么的,或者至少包含一个可以解释的链接。


4
在Windows资源管理器中打开主目录,搜索*.doc,选择所有文件(Ctrl+A),然后将它们复制/粘贴到新目录中... 我最初也是去用命令行来实现这个操作,但使用图形界面的方法更快 :) - Alex
我认为你可以直接搜索*.doc并复制结果! - aliqandil
使用此答案来复制带子文件夹的内容:https://dev59.com/cHM_5IYBdhLWcg3wymc0#26421140 - Sisir
使用此答案复制在线文件 https://dev59.com/cHM_5IYBdhLWcg3wymc0#1224932 - Sisir
6个回答

66
在批处理文件解决方案中
for /R c:\source %%f in (*.xml) do copy %%f x:\destination\
代码的运作方式如下:对于位于目录及其子目录/R中,匹配模式为(\*.xml)的每个文件for,将文件名存储在变量%%f中;随后对于每个文件do,执行copy %%f将该文件复制到目标路径x:\\destination\\。我在我的Windows XP计算机上进行了测试,并且它对我非常有效。但是我使用单个%f变量名版本将其键入命令提示符中,正如上面链接的问题中所述。

1
如果exe文件名中有空格,您将如何解决这个问题? - Euclid
1
@Euclid 我脑海里想到的是将最后的 %%f 改为 '%%f' 以保护空格。 - Simeon Pilgrim
5
非常感谢。在保留原来文件夹的情况下,我们应该如何操作呢?例如:保留文件所处的文件夹名称和树形结构。 - code
1
在不同的子文件夹中具有相同名称的文件需要小心处理,因为你只能拥有其中一个副本。 - Rabskatran
@user1456962 这可以通过稍微复杂一些的脚本来完成,该脚本将完整路径保存到变量中,用新路径替换其中的字符,然后复制到新路径。或者,您也可以使用批处理文件自己进行递归,调用自身并“传入”当前正在处理的子目录。 - ErikE
显示剩余2条评论

59

只需使用带有递归选项的XCOPY命令即可。

xcopy c:\*.doc k:\mybackup /sy

/s将使其“递归”


14
但如果一个文件位于 C: 的子文件夹中,它会复制该子文件夹和 .doc 文件……而不是仅复制文件本身而非其子文件夹。 - JAN
很高兴为您提供额外的声望。如果有一个像这样工作得很好的内置程序,我宁愿不使用脚本。 - Kevin Anderson

6

这就是我转向Powershell的原因。试试看,它很有趣:

Get-ChildItem -Recurse -Include *.doc | % {
    Copy-Item $_.FullName -destination x:\destination
}

6
实际上,您可以只运行gci -rec -inc *.doc | cp -dest X:\Destination,因为 Copy-Item 命令接受管道输入。此外,您可能可以完全摆脱 Get-ChildItem 命令,并直接运行 Copy-Item -Recurse -Include *.doc -Destination C:\Destination,因为 Copy-Item 命令也具有 -Recurse-Include 参数。 - Joey
这是否保留子文件夹结构?似乎不是。 - Louis Rhys
1
@Joey 第一个建议有效,第二个要求“提供以下参数的值:”。尝试将Recurse移动到末尾,然后查看Get-Help Copy-Item -Detailed,最后决定只是尝试你的第一个建议。 ;) - ruffin
为了移动文件,可以修改Joey的解决方案,如下所示: gci -rec -inc *.doc | mv -dest X:\Destination - Rikijs
如果我想包含多个不同的扩展名,比如png、jpg和gif,该怎么办? - xeruf

4

布兰登,简短而简单。同时具有灵活性。

set dSource=C:\Main directory\sub directory
set dTarget=D:\Documents
set fType=*.doc
for /f "delims=" %%f in ('dir /a-d /b /s "%dSource%\%fType%"') do (
    copy /V "%%f" "%dTarget%\" 2>nul
)

希望这能帮到您。
我建议在复制后添加一些检查(使用“||”),但我不确定当“copy /v”遇到错误时会有什么反应。
您可以尝试以下操作:
copy /V "%%f" "%dTarget%\" 2>nul|| echo En error occured copying "%%F".&& exit /b 1

作为副本行。如果您从中获得了一些东西,请告诉我(目前无法测试复制失败..)


1

你也可以使用VBScript

Set objFS = CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
strDestination = "c:\tmp\"
Set objFolder = objFS.GetFolder(strFolder)

Go(objFolder)

Sub Go(objDIR)
  If objDIR <> "\System Volume Information" Then
    For Each eFolder in objDIR.SubFolders       
        Go eFolder
    Next
    For Each strFile In objDIR.Files
        strFileName = strFile.Name
        strExtension = objFS.GetExtensionName(strFile)
        If strExtension = "doc" Then
            objFS.CopyFile strFile , strDestination & strFileName
        End If 
    Next    
  End If  
End Sub 

另存为 mycopy.vbs 并在命令行上运行

c:\test> cscript /nologo mycopy.vbs

0

可以使用以下命令来完成:

for /r "C:\source" %f in (*.doc) do @copy "%f" "C:\destination"

你也可以运行这些来使它更简单

set source="C:\src"
set destination="C:\dest"
set extension=doc

for /r %source% %f in (*.%extension%) do @copy "%f" %destination%

如果您希望复制包含文件类型的父文件夹名称,请尝试使用此命令。
xcopy "C:\src\*.doc" "C:\dest" /sy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接