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

WindowsBatch FileCmdRobocopy

Windows Problem Overview


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.zip and info.txt can 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)?

The resulting directory structure should look like this:

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

Windows Solutions


Solution 1 - Windows

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

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

EDIT: Changed the /S parameter to /E to include empty folders.

Solution 2 - Windows

An alternate solution that copies one file at a time and does not require 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_DIR and name in FILENAMES_TO_COPY. For each existing file xcopy is invoked. FILE_INTERMEDIATE_DIR holds the file's subdirectory path within SOURCE_DIR which needs to be created in DEST_DIR.

Solution 3 - Windows

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

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

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

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

Solution 4 - Windows

If Powershell is an option, you can do this:

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.

Solution 5 - Windows

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

xcopy *.txt /s G:

Solution 6 - Windows

Thanks To Previous Answers. :)

This script named "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.

Any improvement are welcome. :)

Solution 7 - Windows

With find and cp only:

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 ";"

Solution 8 - Windows

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

@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

Solution 9 - Windows

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).

Solution 10 - Windows

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

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

Then you'd cwd to the target and:

$ 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 cvf -  *data.zip *info.txt |  tar xvf - 

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

Solution 11 - Windows

For those using Altap Salamander (2 panels file manager) : in the Options of the Copy popup, just specify the file names or masks. Easy.

Solution 12 - Windows

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

EDIT: If you want to preserve the empty folders (which, on rereading your post, you seem to) use /E instead of /S.

Solution 13 - Windows

Using WinRAR command line interface, you can copy the file names and/or file types to an archive. Then you can extract that archive to whatever location you like. This preserves the original file structure.

I needed to add missing album picture files to my mobile phone without having to recopy the music itself. Fortunately the directory structure was the same on my computer and mobile!

I used:

   rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
  • C:\Downloads\music.rar = Archive to be created
  • X:\music\ = Folder containing music files
  • Folder.jpg = Filename I wanted to copy

This created an archive with all the Folder.jpg files in the proper subdirectories.

This technique can be used to copy file types as well. If the files all had different names, you could choose to extract all files to a single directory. Additional command line parameters can archive multiple file types.

More information in this very helpful link <http://cects.com/using-the-winrar-command-line-tools-in-windows/>

Solution 14 - Windows

I am fine with regular expressions, lazy and averse to installs, so I created a batch file that creates the directory and copies with vanilla DOS commands. Seems laborious but quicker for me than working out robocopy.

  1. Create your list of source files with complete paths, including drive letter if nec, in a text file.
  2. Switch on regular expressions in your text editor.
  3. Add double quotes round each line in case of spaces - search string (.*) replace string "\1", and click replace all
  4. Create two lines per file - one to create the directory, one to copy the file (qqq will be replaced with destination path) - search string (.*) replace string md qqq\1\nxcopy \1 qqq\1\n and click replace all
  5. Remove the filename from the destination paths – search \\([^\\^"]+)"\n replace \\"\n
  6. Replace in the destination path (in this example A:\src and B:\dest). Turn OFF regular expressions, search qqq"A:\src\ replace B:\dest\ and click replace all.

md will create nested directories. copy would probably behave identically to xcopy in this example. You might want to add /Y to xcopy to suppress overwrite confirms. You end up with a batch file like so:

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

repeated for every file in your original list. Tested on Win7.

Solution 15 - Windows

To do this with drag and drop use winzip there's a dir structure preserve option. Simply create a new .zip at the directory level which will be your root and drag files in.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionM4NView Question on Stackoverflow
Solution 1 - WindowsaphoriaView Answer on Stackoverflow
Solution 2 - WindowssakraView Answer on Stackoverflow
Solution 3 - WindowsGabe RainbowView Answer on Stackoverflow
Solution 4 - WindowsNeilView Answer on Stackoverflow
Solution 5 - WindowsOsbert SnudgeView Answer on Stackoverflow
Solution 6 - WindowsRhak KahrView Answer on Stackoverflow
Solution 7 - WindowsRopView Answer on Stackoverflow
Solution 8 - WindowsPatrick CuffView Answer on Stackoverflow
Solution 9 - WindowsPauliusView Answer on Stackoverflow
Solution 10 - WindowsJohnPView Answer on Stackoverflow
Solution 11 - WindowsHugo PView Answer on Stackoverflow
Solution 12 - WindowsgkrogersView Answer on Stackoverflow
Solution 13 - WindowsJim_JoatView Answer on Stackoverflow
Solution 14 - WindowsChrisView Answer on Stackoverflow
Solution 15 - WindowsGnoy DavView Answer on Stackoverflow