copy of files in windows cmd batch - windows

I really cannot find anything to this problem:
I have a folder C:\dir1\dir2 I get this directory via reading a file so I don't know the name of dir1 or dir2 upfront. I want to copy dir2 into a target directory C:\target. At the end I want to have C:\target\dir2 and that dir2 in target shall have all the files which have been in the source of dir2. When I try xcopy with /s switch it copies the files in the source dir2 directly into target without creating dir2 in target. How can I make sure that this directory is created?
I must achieve that dir2 is created automatically.
EDIT:
for /F "tokens=*" %%i in (%maindir%\mydir.txt) do call :process2 %%i
:process2
set sourcefile=%*
xcopy /s "%sourcefile%" target
is basically the part of my batch file in question. Where in mydir.txt I get some directory like C:\dir1\dir2 which contains files file1 file2 etc. In target I have now
target\file1
target\file2
but I want target\dir2\file1 and target\dir2\file2
Hope that makes it a bit clearer.

#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir\with space"
SET "destdir=c:\destdir"
FOR /f "delims=" %%a IN ("%sourcedir%") DO (
XCOPY /s "%sourcedir%" "%destdir%\%%~nxa\"
)
GOTO :EOF
This should get the job done for you. I'll presume you've already got sourcedir set from your file – I just used a directory I had which happens to contain spaces in its name. Possibly you'd want to append >nul to the XCOPY line to suppress messages.

Your question is a little unclear, but if I understand it correctly, you should have a look at the mkdir command. That will make your directory - only if the directory doesn't already exist. The syntax is:
MKDIR [drive:]path
For example, mkdir \2014\photos\beach makes the directory "2014" in the current directory ( use CD) with the sub folders "photos" and "beach".
That being said, if you have proper syntax for xcopy, it should create the new directory for you IF it doesn't already exist. Have a look again at xcopy.
If the directory does exist, this is a pretty "sure-fire" way to remove it before trying to make it again:
if exist {directory} rd /s /q {directory}

Related

Moving files from more than one folder to the parent directory using CMD

I have a folder Target contains multiple folders,
each folder contains one file with the same name of the folder
I want to move the files in folders Part1,Part2,Part3,Part4 and Part5
to parent folder ("Target" in this case) using cmd then delete the folders.
The result should be like that :
In Linux i could've used mv Part*\*.* ..
I've tried copy "Part*\*" "" command,
but it doesn't work.
Use a For loop. The key to getting directory names in this code is "dir /a:d" which only lists directories. I put that into the %%a variable. Use %~dp0 to refer to the directory the batch file is in. If your bat is somewhere else, do a find and replace all for that to the directory path you need. Lastly use RMDIR to remove each folder with /q /s to make it silent and remove all files within the directory (part1 part2 etc...) and the directories themselves.
#echo off
for /f "tokens=* delims=" %%a in ('dir /a:d /b "%~dp0"') do (
copy "%~dp0%%a\*.*" "%~dp0"
RMDIR /q /s "%~dp0%%a"
)
In the Windows Command Prompt, copy "Part*\*" "" cannot work, because wildcards are only permitted in the last element of a path but not somewhere in the middle.
To work around this, use a for /D loop to resolve wildcards in Part*, then let copy deal with the remaining ones:
for /D %I in ("Part*") do #copy "%~I\*" ".."
To move the files rather than to copy, simply replace copy by move. If you want to remove empty sub-directories then, append rd using &&:
for /D %I in ("Part*") do #move "%~I\*" ".." && #rd "%~I"
To use the above code fragments in a batch-file, ensure to double all the %-signs.

Replace multiple files in sub directories with file from a different directory

I would like to take a file named test1.hfl from one directory and replace all the existing test1.hfl files inside the sub directories of the folder runs in my c drive.
I have started the batch file with the following code:
FOR /R C:\Users\----\Documents\Train\Runs\ %%I IN (*test1.hfl) DO COPY /Y C:\Users\----\Documents\test1.hfl %%~fI
But it doesn't work.
Please let me know if you can see something wrong.
try this:
cd /d "C:\Users\----\Documents\Train\Runs"
FOR /D /R \ %%a IN (*) do if exist "%%~a\test1.hfl" echo copy /y "test1.hfl" "%%~a"
Look at the output and remove the word echo if it looks good.
Accepting an answer - how does it work?

Recursively create folder in specific directories

During a recent backup/restore cycle I've realized that I managed to omit the 'tmp' directories from within the '.svn' directories, and because of this I can't update my working copies. The problem goes away if I manually create a new, empty 'tmp' directory so I am looking for a way to recursively go through each folder, find '.svn' ones and create a 'tmp' folder inside them.
As I don't want to mess up the existing folders I thought I's ask for help before I did something silly :)
Comments/suggestions will be appreciated, thanks!
PS: This is on a Windows machine so sadly Bash and other unix utilities are not present.
The script above doesn't work on my on Windows 7 machine. The "dir /b /s .svn" doesn't get all dirs, I get a "File Not Found" error.
I changed the script to have /ad in addition to select directories only and that works! Here is the srcipt which works for me.
#echo off
for /f "usebackq delims=" %%I in (`dir /ad /b /s .svn`) do (
echo Fixing %%I...
mkdir "%%I\tmp"
)
Depends on how many there are.
List the directories with
dir/B/S .svn >dirs.bat
Edit dirs.bat in your editor of choice. Add md at the beginning of each line (since each line begins with something like C: you can use a fairly dumb editor - including notepad - to change C: to md C: ). Add /tmp to the end of each line (replace .svn with .svn\tmp). Save. Run the BAT file
Job done.
Here's how to automate the entire process. Put the following in a file like fixtmp.cmd:
#echo off
for /f "usebackq delims=" %%I in (`dir /b /s .svn`) do (
echo Fixing %%I...
mkdir "%%I\tmp"
)

How can I move the contents of one directory tree into another?

I have a directory which contains files and a number of levels of subdirectories:
C:\Source
I would like to move the contents of C:\Source into:
C:\Destination
Requirements:
All files and all subdirectories
within C:\SourceData must be moved
I will be running the command in a
batch file
I can't use Powershell or
any other scripting languages
Attempt 0
XCOPY /E "C:\Source" "C:\Destination"
This works perfectly, but it copies instead of moves. I can't copy then delete the source as I'm moving a very large set of files and there isn't enough disk space to have two copies of them at a time.
Attempt 1
MOVE "C:\Source" "C:\Destination"
This moves the entire C:\Source directory into C:\Destination so I end up with:
C:\Destination\Source
Attempt 2
With some help from this question and accepted answer I came up with:
for /r "C:\Source" %%x in (*) do move "%%x" "C:\Destination"
This moves the files within C:\Source but not the subdirectories or their contents. Note that I used %%x instead of %x as I'm using it in a batch file.
Using FOR seems promising but I'm not sure I've used the right syntax? Have I missed something?
Attempt 3
As suggested by Nick D, I tried rename:
RENAME "C:\Source" Destination
For the example scenario I gave this works fine. Unfortunately my real Destination directory is at a different level to the Source directory and this doesn't seem to be supported:
C:\>REN /?
Renames a file or files.
RENAME [drive:][path]filename1 filename2.
REN [drive:][path]filename1 filename2.
Note that you cannot specify a new drive or path for your destination file.
I get "The syntax of the command is incorrect." errors if I try to specify a more complex destination path, for example:
RENAME "C:\Source" "C:\MyOtherDirectory\Destination"
RENAME "C:\Source" "MyOtherDirectory\Destination"
Undoubtedly use robocopy. It is a simple but brilliantly useful tool.
robocopy /move /e sourcedir destdir
This will move all the files and folders, including empty ones, deleting each original file after it has moved it.
If you don't have robocopy installed you can download it by itself or as part of a Microsoft resource kit.
Update:
Adjusted code to a. check whether folders already exist at the destination, in which case move files in that folder over (and continue traversing the source directory structure), otherwise move the folder wholesale.
At the end of the script the source folder is removed altogether to eliminate these folders which have had their files moved over to an already existent folder at the destination (meaning these folders have been emptied but not deleted at the source).
Additionally we check whether a folder is both empty and already exists at the destination in which case we do nothing (and leave the source folder to be deleted to the last line of the script). Not doing this results in "The filename, directory name, or volume label syntax is incorrect." errors.
Phew! Please let me know how you get on with this! I have tested this and it seems to be working well.
for /d /r "c:\source" %%i in (*) do if exist "c:\destination\%%~ni" (dir "%%i" | find "0 File(s)" > NUL & if errorlevel 1 move /y "%%i\*.*" "c:\destination\%%~ni") else (move /y "%%i" "c:\destination")
move /y c:\source\*.* c:\destination
rd /s /q c:\source
In response to ufukgun's answer:
xcopy C:\Source\* C:\Destination\* /s /e /i /Y
/s - Copies directories and subdirectories except empty ones.
/e - Copies directories and subdirectories, including empty ones. Same as /S /E. May be used to modify /T.
/i - If destination does not exist and copying more than one file, assumes that destination must be a directory.
/y - Suppresses prompting to confirm you want to overwrite an existing destination file.
As stated in another answer, using xcopy may be not as efficient as it would be a native move command that only changes pointers in the filesystem.
Since XCOPY works, you could use XCOPY and DELETE, it's a workaround, but should work?
on Vista use
robocopy source destination /MIR
/MIR .. mirror a complete directory tree (also deletes files in the destination)
else
xcopy
Of course you have to delete the source afterwards :)
I have a directory which contains
files and a number of levels of
subdirectories:
C:\Source
I would like to move the contents of
C:\Source into:
C:\Destination
Maybe I'm missing something, but can't you just rename the folder?
As sent on twitter:
Try combining attempt 3 with attempt 1. Rename to get the destination folder correct, then move "Destination" to the correct place.
#echo on
set SOURCE=C:\Source
set DESTINATION=C:\Destination
xcopy %SOURCE%\* %DESTINATION%\* /s /e /i /Y
PAUSE
i use batch file like this...
or simply call:
xcopy C:\Source\* C:\Destination\* /s /e /i /Y
I use a utility called xxcopy. It can move files and have many useful options, you can use it like this :
xxcopy C:\Source C:\Destination /E /RC
the options :
/E to copy everything even empty folders
/RC to remove every source file after each successful copy
you can download free copy of xxcopy for personal use from :
http://www.xxcopy.com/xcpydnld.htm
Maybe a little off-topic, but still usefull:
Some people suggest to just copy + delete the source files, but
moving files is not the same as copying + deleting!
When using the (x)copy function, you allocate new space on the same volume on a harddisk. After the copying the files, the old files (the old allocated space which was required for the files) are beign marked as deleted. While you will achieve the same result as an end-user, moving does something diffrent and more efficient.
Moving files actually only changes some records in the MFT (master file table). These changes only consist of a different path for the user to locate its files. Physically the files still remain in the same sectors on the harddisk.
If all your trying to do is move a directory and the content up one level:
MOVE folder_you_wan_to_move ..
Note that .. refers to the next directory up.
I leave this code I have written based on ljs's attempt,
It moves directory trees as Windows does, overwriting the files that already exists in destination with those in source, and avoiding the slow copy and erase method except if the destination is in a different drive.
If your S.O is not in english must change line 6 with the text used by the Dir command when it finds 0 files.
movedir.bat source_dir destination_dir
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
if %1.==. echo movedir dir1[\*] dir2 & echo move dir1 inside dir2 overwriting coincident files & echo option \* moves only dir1 content & goto end
set S=%~f1
set D=%~f2
set "noFiles= 0 File"
set "R=0" rem R is option [\*] flag
if %S:~-2%.==\.. set "S=%S:~,-2%" & set "R=1"
if not exist "%S%" goto paramERR
if not exist "%D%" goto paramERR
set "Trim=0" & set "Sc=%S%"
:LP
set /A Trim+=1 & (set "Sc=!Sc:~1!") & if NOT !Sc!.==. goto LP
if %R%==0 (if exist "%D%\%~n1%~x1" (set "D=%D%\%~n1%~x1")) else move /y "%S%" "%D%" & goto end
CALL:movefiles "%S%" "%D%"
for /D /R "%S%" %%I in (*) do (set "Way=%%~fI") & (set "Way=!Way:~%Trim%!") & if exist "%D%!Way!" (CALL:movefiles "%%I" "%D%!Way!") else (move /y "%%I" "%D%!Way!\.." > NUL)
rd /s/q "%S%" & if %R%==1 md "%S%"
goto end
:movefiles
dir %1 | find "%noFiles%" > NUL & if ERRORLEVEL 1 move /y "%~1\*.*" %2 > NUL
goto :eof
:paramERR
echo Source or Destination does not exist
:end
I think the easiest thing you could do is to modify your Attempt 2
from
MOVE "C:\Source" "C:\Destination"
to
MOVE "C:\Source\*" "C:\Destination"
KISS ;-)
Edit: this seem not to work, so my advice is to trash away the crappy DOS command line and use Cygwin with BASH as a shell! (or just add the cygwin binaries to the path so you can use mv within DOS, thus not having to change the shell as your requirements state).

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

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
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.
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.
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.
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.
To copy all text files to G: and preserve directory structure:
xcopy *.txt /s G:
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. :)
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 ";"
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
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).
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.
For those using Altap Salamander (2 panels file manager) : in the Options of the Copy popup, just specify the file names or masks. Easy.
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.
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/
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.
Create your list of source files with complete paths, including drive letter if nec, in a text file.
Switch on regular expressions in your text editor.
Add double quotes round each line in case of spaces - search string (.*) replace string "\1", and click replace all
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
Remove the filename from the destination paths – search \\([^\\^"]+)"\n replace \\"\n
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.
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.

Resources