如何复制目录结构但仅包括某些文件(使用Windows批处理文件)


103

如标题所述,如何递归复制目录结构,但只包含一些文件。例如,给出以下目录结构:

folder1
  folder2
    folder3
      data.zip
      info.txt
      abc.xyz
    folder4
    folder5
      data.zip
      somefile.exe
      someotherfile.dll

文件data.zipinfo.txt可以出现在目录结构中的任何位置。如何复制完整的目录结构,但仅包含名为data.zip和info.txt的文件(应忽略​​所有其他文件)?

生成的目录结构应如下所示:

copy_of_folder1
  folder2
    folder3
      data.zip
      info.txt
    folder4
    folder5
      data.zip

Answers:


169

您没有提及它是否仅必须是批处理,但是如果可以使用ROBOCOPY,请尝试以下操作:

ROBOCOPY C:\Source C:\Destination data.zip info.txt /E

编辑:更改/S参数/E以包括空文件夹。


我可以用这种语法复制* .zip吗?我尝试只写* .zip而不是data.zip,但是它没有复制文件,仅复制文件夹。我也尝试过?.zip
Niels Brinch 2012年

@Niels Brinch是的,您应该能够做到。您使用的确切命令行是什么?
Aphoria 2012年

1
ROBOCOPY C:\ Source C:\ Destination * .zip / E
Niels Brinch 2012年

奇怪的。您正在使用什么操作系统?您是否具有必要的文件/文件夹权限?我刚刚在Win 7上测试并*.zip为我工作。
aphoria 2012年

真!?我也在使用Win7。尝试时,它不会复制任何文件。仅文件夹。我会再尝试。(虽然我们在这,什么是语法包括超过* .zip文件-假设* .zip或* .JPG。
尼尔斯BRINCH

29

一次复制一个文件且不需要ROBOCOPY的替代解决方案:

@echo off
setlocal enabledelayedexpansion

set "SOURCE_DIR=C:\Source"
set "DEST_DIR=C:\Destination"
set FILENAMES_TO_COPY=data.zip info.txt

for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
    if exist "%%F" (
        set FILE_DIR=%%~dpF
        set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
        xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
    )
)

外部for语句生成中的子目录SOURCE_DIR和中的名称的任何可能的路径组合FILENAMES_TO_COPY。对于每个现有文件,将调用xcopy。FILE_INTERMEDIATE_DIR存放SOURCE_DIR需要在中创建文件的子目录路径DEST_DIR


1
我需要从文件夹和子文件夹复制所有照片,此批处理脚本很有帮助。刚刚将set FILENAMES_TO_COPY=data.zip info.txt上面的行更改为set FILENAMES_TO_COPY=*.jpg
Kai Noack

我收到一个错误消息,因为文件路径上有空格(SOURCE_DIR =“ C:\ Origin Test”,DEST_DIR =“ C:\ Dest Test”,错误:Test“”目前是意外的)。我尝试通过!var更改%var%!到处都是,但没有成功。关于如何解决这个问题的任何线索?整个结构充满了带空格的文件夹名称。
ricardo.scholz '19

1
尝试set "SOURCE_DIR=C:\Origin Test"set "DEST_DIR=C:\Dest Test"。注意双引号的位置。
萨克拉

13

尝试将find(即文件路径)的输出管道传输到cpio中

find . -type f -name '*.jpg' | cpio -p -d -v targetdir/

cpio检查目标文件上的时间戳-这样既安全又快速。

习惯后,请删除-v以加快操作速度。


2
@Christian它依赖于cpio,这不是标准安装的一部分。
Crashworks 2014年

8

如果可以选择Powershell,则可以执行以下操作:

Copy-Item c:\sourcePath d:\destinationPath -filter data.zip -recurse

主要缺点是它会复制所有文件夹,即使它们最终将为空,因为没有文件与您指定的过滤器匹配。因此,除了少数几个具有所需文件的文件夹之外,您最终可能会得到一棵充满空文件夹的树。


第二次运行将更改目标。(它将文件放在子文件夹中。)如果您问我,这是一种愚蠢的行为。您将需要rm -r -ErrorAction:SilentlyContinue d:\destinationPath在复制之前运行以解决此问题。
MakotoE19年

7

感谢以前的答案。:)

该脚本名为“ r4k4copy.cmd”:

@echo off
for %%p in (SOURCE_DIR DEST_DIR FILENAMES_TO_COPY) do set %%p=
cls
echo :: Copy Files Including Folder Tree
echo :: http://stackoverflow.com
rem     /questions/472692/how-to-copy
rem     -a-directory-structure-but-only
rem     -include-certain-files-using-windows
echo :: ReScripted by r4k4
echo.
if "%1"=="" goto :NoParam
if "%2"=="" goto :NoParam
if "%3"=="" goto :NoParam
setlocal enabledelayedexpansion
set SOURCE_DIR=%1
set DEST_DIR=%2
set FILENAMES_TO_COPY=%3
for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
if exist "%%F" (
set FILE_DIR=%%~dpF
set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
)
)
goto :eof
:NoParam
echo.
echo Syntax: %0 [Source_DIR] [Dest_DIR] [FileName]
echo Eg.   : %0 D:\Root E:\Root\Lev1\Lev2\Lev3 *.JPG
echo Means : Copy *.JPG from D:\Root to E:\Root\Lev1\Lev2\Lev3

它接受“源”,“目标”和“文件名”的变量。它也只能复制指定类型的文件或选择性文件名。

任何改进都欢迎。:)


5

仅使用find和cp:

mkdir /tmp/targetdir
cd sourcedir
find . -type f -name '*.zip' -exec cp -p --parents {} /tmp/targetdir ";"
find . -type f -name '*.txt' -exec cp -p --parents {} /tmp/targetdir ";"

4

与Paulius的解决方案类似,但是您不关心的文件不会被复制然后删除:

@echo OFF

:: Replace c:\temp with the directory where folder1 resides.
cd c:\temp

:: You can make this more generic by passing in args for the source and destination folders.
for /f "usebackq" %%I in (`dir /b /s /a:-d folder1`) do @echo %%~nxI | find /V "data.zip" | find /v "info.txt" >> exclude_list.txt
xcopy folder1 copy_of_folder1 /EXCLUDE:exclude_list.txt /E /I

4

要将所有文本文件复制到G:并保留目录结构:

xcopy *.txt /s G:

是否可以递归工作,例如从子文件夹复制所有.txt并保留相对于基本目录的目录结构?
米卡,

3

那只是两个简单的命令,但是除非您不需要复制的文件很小,否则我不建议您这样做。这是因为这将复制所有文件,然后删除副本中不需要的文件。

xcopy /E /I folder1 copy_of_folder1
for /F "tokens=1 delims=" %i in ('dir /B /S /A:-D copy_of_files ^| find /V "info.txt" ^| find /V "data.zip"') do del /Q "%i"

当然,第二个命令有点长,但是可以用!

另外,这种方法不需要您下载并安装任何第三方工具(Windows 2000+ BATCH为此提供了足够的命令)。


非常感谢。正如您提到的那样,这是不理想的,因为(在我的情况下)通常必须复制的文件很小,而不应复制的文件则很大(可能有很多)。
M4N

2

在Linux和其他UNIX系统上,使用该tar命令可以轻松完成此操作。

$ tar cvf /tmp/full-structure.tar *data.zip *info.txt

然后,您将cwd转到目标并:

$ tar xvf /tmp/full-structure.tar 

当然,您可以将第一个tar的输出传递到第二个tar,但逐步了解它的工作更容易理解和解释。我在以下命令中缺少必要的cd / to / new / path /-我只是不记得现在该怎么做。希望其他人可以添加它。

$ tar cvf -  *data.zip *info.txt |  tar xvf - 

Tar(nutar)也可在Windows上使用,但我可能会xcopy在该平台上自己使用该方法。


tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt为我工作
ssinganamalla 2013年

“ tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt”和“ tar cvf /tmp/full-structure.tar * data.zip * info.txt”都给了我3个错误:(1)“ tar:* data.zip:无法统计:没有这样的文件或目录”,(2)“ tar * info.txt:无法统计:没有这样的文件或目录”,(3)“ tar:退出于由于先前的错误导致的故障状态”。我可以从文件夹中进行所有这些操作吗?我不明白这种方法。
user1271772

问题说WINDOWS
Anfelipe

Win10具有WSL,这使其有效。tar在Windows上已有20多年的历史,并且自MS-DOS时代开始就使用管道。在任何外壳环境中,PWD都很重要。PWD-当前工作目录。我会承认这种解决方案对于最终用户而言较少,而对于高级用户或程序员而言则更多。
JohnP

1
XCOPY /S folder1\data.zip copy_of_folder1  
XCOPY /S folder1\info.txt copy_of_folder1

编辑:如果您想保留空文件夹(在重新阅读帖子时似乎使用),则使用/ E而不是/ S。


1
它不保留文件夹结构。
Paulius,2009年

/ E选项保留文件夹结构,包括在必要时创建空文件夹。该文件名也可以使用通配符(例如folder1 \ *。zip)。当我传递不存在的完整文件名时,我只会收到“找不到文件错误”(在这种情况下,我会得到“找不到文件-xxx.xxx 0文件已复制”。当我给它一个模式时没有返回文件(如文件夹1 \ * ZZZ),我只是得到“0文件(* S)复制”。
gkrogers

1

使用WinRAR命令行界面,可以将文件名和/或文件类型复制到归档文件中。然后,您可以将该存档解压缩到所需的任何位置。这将保留原始文件结构。

我需要将丢失的专辑图片文件添加到手机中,而不必重新复制音乐本身。幸运的是,我的计算机和移动设备上的目录结构是相同的!

我用了:

   rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
  • C:\ Downloads \ music.rar =要创建的存档
  • X:\ music \ =包含音乐文件的文件夹
  • Folder.jpg =我要复制的文件名

这将在适当的子目录中创建所有Folder.jpg文件的存档。

该技术也可以用于复制文件类型。如果文件名称不同,则可以选择将所有文件提取到单个目录中。其他命令行参数可以归档多种文件类型。

有关此非常有用的链接的详细信息,请参见http://cects.com/using-the-winrar-command-line-tools-in-windows/


1

对于使用Altap Salamander(2面板文件管理器)的用户:在“复制”弹出窗口的“选项”中,只需指定文件名或掩码即可。简单。


0

我对正则表达式,懒惰和不喜欢安装都很好,所以我创建了一个批处理文件,该文件创建了目录并使用香草DOS命令进行了复制。对于我来说,这似乎比较费力,但是比制定电子复印本更快。

  1. 在文本文件中创建具有完整路径的源文件列表,包括完整的驱动器号。
  2. 在文本编辑器中打开正则表达式。
  3. 如果出现空格,请在每行周围加上双引号-搜索字符串(.*)替换字符串"\1",然后单击全部替换
  4. 每个文件创建两行-一个用于创建目录,一个用于复制文件(qqq将替换为目标路径)-搜索字符串(.*)替换字符串md qqq\1\nxcopy \1 qqq\1\n,然后单击全部替换
  5. 从目标路径中删除文件名–搜索\\([^\\^"]+)"\n替换\\"\n
  6. 替换为目标路径(在此示例中为A:\srcB:\dest)。关闭正则表达式,搜索qqq"A:\src\替换B:\dest\并单击全部替换。

md将创建嵌套目录。在此示例中,copy的行为可能与xcopy相同。您可能想要在xcopy中添加/ Y以禁止覆盖确认。您最终得到一个像这样的批处理文件:

md "B:\dest\a\b\c\"
xcopy "C:\src\a\b\c\e.xyz" "B:\dest\a\b\c\e.xyz"

对原始列表中的每个文件重复此操作。在Win7上测试。


-1

要使用Winzip拖放操作,可以使用dir结构保存选项。只需在目录级别创建一个新的.zip文件即可,它将成为您的根目录并拖动文件。


谢谢,但是我一直在寻找脚本(批处理)文件中使用的解决方案。因此,无需拖放...
M4N
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.