Copy Every File of Entire Directory Structure into Base Path of Another

Copy every file of entire directory structure into base path of another

you are looking for ways to flatten the directory

find /images -iname '*.jpg' -exec cp --target-directory /newfolder/ {} \;

find all files iname in case insensitive name mode.

cp copy once to --target-directory named /newfolder/.

{} expand the list from find into the form of /dir/file.jpg /dir/dir2/bla.jpg.

Find all files and copy to another destination keeping the folder structure

Stack Overflow is not a free code writing service, see help topic What topics can I ask about here?

However, I have nevertheless written the entire batch code for this task. Learn from this commented code and next time try to write the batch code by yourself and ask only if you stick on a problem you can't solve by yourself after several trials and not finding a solution on Stack Overflow or any other website.

The paths of source and target base folder must be defined at top of the batch script below.

The text file containing the name of the files to copy line by line must be named FileNames.txt and must be stored in source base folder with using batch code below.

@echo off
setlocal EnableExtensions EnableDelayedExpansion

rem Define source and target base folders.

rem Note:

rem The paths should not contain an equal sign as then the
rem string substitutions below would not work as coded. The
rem target base folder can be even a subfolder of the source
rem base folder.

set "SourceBaseFolder=C:\Temp"
set "TargetBaseFolder=C:\Temp\OutputFolder"

rem Set source base folder as current directory. The previous
rem current directory is restored by command endlocal at end.

if not exist "%SourceBaseFolder%\*" (
echo %~nx0: There is no folder %SourceBaseFolder%
set "ErrorCount=1"
goto HaltOnError
)

cd /D "%SourceBaseFolder%"

if not exist "FileNames.txt" (
echo %~nx0: There is no file %SourceBaseFolder%\FileNames.txt
set "ErrorCount=1"
goto HaltOnError
)

rem For each file name in text file FileNames.txt in
rem source base folder the loops below do following:

rem 1. Search recursively for a file with current file name
rem in entire directory tree of source base folder.

rem 2. If a file could be found, check its path. Skip the
rem file if the path of found file contains the target
rem folder path to avoid copying files to itself. This
rem IF condition makes it possible that target base
rem folder is a subfolder of source base folder.

rem 3. Create the folders of found file relative to source
rem base path in target base folder. Then check if this
rem was successful by verifying if the target folder
rem really exists and copy the file on existing folder or
rem output an error message on failure creating the folder.

set "ErrorCount=0"
for /F "usebackq delims=" %%N in ("FileNames.txt") do (
for /R %%J in ("%%N*") do (
set "FilePath=%%~dpJ"
if "!FilePath:%TargetBaseFolder%=!" == "!FilePath!" (
set "TargetPath=%TargetBaseFolder%\!FilePath:%SourceBaseFolder%\=!"
md "!TargetPath!" 2>nul
if exist "!TargetPath!\*" (
echo Copying file %%~fJ
copy /Y "%%~fJ" "!TargetPath!" >nul
) else (
set /A ErrorCount+=1
echo Failed to create directory !TargetPath!
)
)
)
)

:HaltOnError
if %ErrorCount% NEQ 0 (
echo.
pause
)
endlocal

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /? ... for an explanation of %~nx0
  • copy /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

And read also the Microsoft article about Using command redirection operators to understand 2>nul for suppressing error messages written to STDERR.

How to copy the contents of all subdirectories into one directory, retaining structure and overwriting duplicates with a batch file?

This should work:

@ECHO OFF
SETLOCAL EnableDelayedExpansion



REM **************************************************

SET source_dir=C:\MyFolder

SET target_dir=C:\NewFolder

REM **************************************************



FOR /F "delims=" %%G IN ('DIR /S /B /A:D "%source_dir%"') DO (
SET "folder_name=%%G"
CALL :copy
)


ECHO. & ECHO. & ECHO. & ECHO. & ECHO. & ECHO Done^^!
PAUSE
EXIT


:copy
SET "target_folder_name=!folder_name:%source_dir%\=!"
ECHO !target_folder_name! | FINDSTR /C:"\\" >nul && SET "target_folder_name=!target_folder_name:*\=!" || SET "target_folder_name=."

ROBOCOPY "!folder_name!" "%target_dir%\!target_folder_name!" /IT
EXIT /B

This basically removes the C:\MyFolder\*\ from each folder path and the remaining name, path or . (if it's a direct sub-folder of C:\MyFolder) is added to the target_dir path.


If a path remains you could also shrink this path to only a name and combine all files of all sub-directories into one sub-folder.

For this, simply replace the :copy bit with this:

:copy
SET "target_folder_name=!folder_name:%source_dir%\=!"

ECHO !target_folder_name! | FINDSTR /C:"\\" >nul || SET "target_folder_name=."

SET "loop_counter=0"

:loop
SET /A "loop_counter=%loop_counter%+1"
IF %loop_counter%==10 (ECHO Error: Could not copy !folder_name! && EXIT /B)
ECHO !target_folder_name! | FINDSTR /C:"\\" >nul && SET "target_folder_name=!target_folder_name:*\=!" && SET /A "counter=%counter%+1" && GOTO loop

ROBOCOPY "!folder_name!" "%target_dir%\!target_folder_name!" /IT
EXIT /B

This adds a loop to remove up to 10 parent directories if any and a loop_counter to prevent an endless loop. Obviously you can have more loops by simply adjusting the 10 in this IF-Statement:    IF %loop_counter%==10.

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

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.

Recursive copy of a specific file type maintaining the file structure in Unix/Linux?

rsync is useful for local file copying as well as between machines. This will do what you want:

rsync -avm --include='*.jar' -f 'hide,! */' . /destination_dir

The entire directory structure from . is copied to /destination_dir, but only the .jar files are copied. The -a ensures all permissions and times on files are unchanged. The -m will omit empty directories. -v is for verbose output.

For a dry run add a -n, it will tell you what it would do but not actually copy anything.

How do I copy an entire directory of files into an existing directory using Python?

This limitation of the standard shutil.copytree seems arbitrary and annoying. Workaround:

import os, shutil
def copytree(src, dst, symlinks=False, ignore=None):
for item in os.listdir(src):
s = os.path.join(src, item)
d = os.path.join(dst, item)
if os.path.isdir(s):
shutil.copytree(s, d, symlinks, ignore)
else:
shutil.copy2(s, d)

Note that it's not entirely consistent with the standard copytree:

  • it doesn't honor symlinks and ignore parameters for the root directory of the src tree;
  • it doesn't raise shutil.Error for errors at the root level of src;
  • in case of errors during copying of a subtree, it will raise shutil.Error for that subtree instead of trying to copy other subtrees and raising single combined shutil.Error.

How to copy all files from a directory and its subdirectories to another dir?

You can use find to get the desired source files, and then use cp within the -exec predicate of find to copy the files to the desired destination. With GNU cp:

find /dir1/ -type f \( -name '*.txt' -o -name '*.jpg' \) -exec cp -t /dir2/ {} + 

POSIX-ly:

find /dir1/ -type f \( -name '*.txt' -o -name '*.jpg' \) -exec cp {} /dir2/ \; 

Copying files to directory whilst retaining directory structure from list

xcopy can't know the folder structure when you explicitly pass source file path instead of a source directory. In a path like C:\foo\bar\baz.txt the base directory could be any of C:\, C:\foo\ or C:\foo\bar\.

When working with a path list, you have to build the destination directory structure yourself. Resolve paths from text file to relative paths, join with destination directory, create parent directory of file and finally use PowerShell's own Copy-Item command to copy the file.

$Filelocs = Get-Content 'locations.txt'

# Base directory common to all paths specified in "locations.txt"
$CommonInputDir = 'C:\redacted\Policies'

# Where files shall be copied to
$Destination = 'C:\Redacted\output'

# Temporarily change current directory -> base directory for Resolve-Path -Relative
Push-Location $CommonInputDir

Foreach ($Loc in $Filelocs) {

# Resolve input path relative to $CommonInputDir (current directory)
$RelativePath = Resolve-Path $Loc -Relative

# Resolve full target file path and directory
$TargetPath = Join-Path $Destination $RelativePath
$TargetDir = Split-Path $TargetPath -Parent

# Create target dir if not already exists (-Force) because Copy-Item fails
# if directory does not exist.
$null = New-Item $TargetDir -ItemType Directory -Force

# Well, copy the file
Copy-Item -Path $loc -Destination $TargetPath
}

# Restore current directory that has been changed by Push-Location
Pop-Location

Possible improvements, left as an exercise:

  • Automatically determine common base directory of files specified in "locations.txt". Not trivial but not too difficult.
  • Make the code exception-safe. Wrap everything between Push-Location and Pop-Location in a try{} block and move Pop-Location into the finally{} block so the current directory will be restored even when a script-terminating error occurs. See about_Try Catch_Finally.

Moving all files from one directory to another using Python

Try this:

import shutil
import os

source_dir = '/path/to/source_folder'
target_dir = '/path/to/dest_folder'

file_names = os.listdir(source_dir)

for file_name in file_names:
shutil.move(os.path.join(source_dir, file_name), target_dir)

Copy Files From Folders and SubFolders Automatically

Test this batch file - make sure that d:\target exists already.

@echo off
for /r "c:\base\folder" %%a in (*.mp3) do copy /y "%%a" "d:\target"

For use at the cmd prompt reduce the %% in each spot to a single %



Related Topics



Leave a reply



Submit