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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/472692/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:58:16  来源:igfitidea点击:

How to copy a directory structure but only include certain files (using windows batch files)

windowsbatch-filecmdrobocopy

提问by M4N

As the title says, how can I recursively copy a directory structure but only include some files. E.g given the following directory structure:

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

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

The files data.zipand info.txtcan appear everywhere in the directory structure. How can I copy the full directory structure, but only include files named data.zip and info.txt (all other files should be ignored)?

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

The resulting directory structure should look like this:

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

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

回答by aphoria

You don't mention if it has to be batch only, but if you can use ROBOCOPY, try this:

你没有提到它是否必须只是批处理,但如果你可以使用ROBOCOPY,试试这个:

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

EDIT: Changed the /Sparameter to /Eto include empty folders.

编辑:将/S参数更改/E为包含空文件夹。

回答by sakra

An alternate solution that copies one file at a time and does not require ROBOCOPY:

一次复制一个文件并且不需要 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!"
    )
)

The outer for statement generates any possible path combination of subdirectory in SOURCE_DIRand name in FILENAMES_TO_COPY. For each existing file xcopy is invoked. FILE_INTERMEDIATE_DIRholds the file's subdirectory path within SOURCE_DIRwhich needs to be created in DEST_DIR.

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

回答by Gabe Rainbow

try piping output of find (ie. the file path) into cpio

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

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

cpio checks timestamp on target files -- so its safe and fast.

cpio 检查目标文件上的时间戳——因此它安全且快速。

remove -v for faster op, once you get used to it.

一旦你习惯了,删除 -v 以获得更快的操作。

回答by Neil

If Powershell is an option, you can do this:

如果 Powershell 是一个选项,您可以这样做:

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

The main disadvantage is it copies all folders, even if they will end up being empty because no files match the filter you specify. So you could end up with a tree full of empty folders, in addition to the few folders that have the files you want.

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

回答by Rhak Kahr

Thanks To Previous Answers. :)

感谢以前的答案。:)

This script named "r4k4copy.cmd":

这个名为“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

It accepts variable of "Source", "Destination", and "FileName". It also can only copying specified type of files or selective filenames.

它接受“Source”、“Destination”和“FileName”变量。它也只能复制指定类型的文件或选择性文件名。

Any improvement are welcome. :)

欢迎任何改进。:)

回答by Rop

With find and cp only:

仅使用 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 ";"

回答by Osbert Snudge

To copy all text files to G: and preserve directory structure:

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

xcopy *.txt /s G:

回答by Patrick Cuff

Similar to Paulius' solution, but the files you don't care about are not copied then deleted:

类似于 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

回答by Paulius

That's only two simple commands, but I wouldn't recommend this, unless the files that you DON'T need to copy are small. That's because this will copy ALL files and then remove the files that are not needed in the copy.

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

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"

Sure, the second command is kind of long, but it works!

当然,第二个命令有点长,但它有效!

Also, this approach doesn't require you to download and install any third party tools (Windows 2000+ BATCH has enough commands for this).

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

回答by JohnP

Under Linux and other UNIX systems, using the tarcommand would do this easily.

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

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

Then you'd cwd to the target and:

然后你会 cwd 到目标和:

$ tar xvf /tmp/full-structure.tar 

Of course you could pipe the output from the first tar into the 2nd, but seeing it work in steps is easier to understand and explain. I'm missing the necessary cd /to/new/path/ in the following command - I just don't recall how to do it now. Someone else can add it, hopefully.

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

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

Tar (gnutar) is available on Windows too, but I'd probably use the xcopymethod myself on that platform.

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