Computing.Net > Forums > Programming > .bat program to copy recursively

.bat program to copy recursively

Reply to Message Icon

Original Message
Name: giovanigonzales
Date: July 9, 2007 at 19:36:43 Pacific
Subject: .bat program to copy recursively
OS: Windows XP
CPU/Ram: 512
Model/Manufacturer: DELL
Comment:

Hello,
I need a script to copy a directory recursively, but instead of re-creating the tree structure, to copy all files in a single folder, appending the directories names as sufix to the file names.
For example i have:

sourcedir:
folder01:
file1, file2, file3
folder02:
file1, file2, file3

the result must be:

destdir:
folder01_file1, folder01_file2, folder01_file3, folder02_file1, folder02_file2, folder02_file3

I know how to do that in .bash but i need a .bat file to do it also, and I'm not good at all in Windows batch scripting

many thanks



Report Offensive Message For Removal

Response Number 1
Name: Mechanix2Go
Date: July 10, 2007 at 08:04:04 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Try this. After previewing, remove the echo before copy to activate it.

::== recurc.bat
:: copies all files in tree to dest, prepending orig DIRname

@echo off
setLocal EnableDelayedExpansion

set /p src=source ?
set /p dest=dest ?

pushd !src!

for /f "tokens=* delims= " %%a in ('dir/b/ad') do (
pushd %%a
set DN=%%a
for /f "tokens=* delims= " %%F in ('dir/b/a-d') do (
echo copy %%F !dest!\!DN!%%F
)
popd
)
::==


=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal

Response Number 2
Name: Mechanix2Go
Date: July 10, 2007 at 12:38:51 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

After thinking about this for a while, I see that it hets ONLY the files in dirs immediately below src.

If it needs to go deeper, that will take more doing.



=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal

Response Number 3
Name: FishMonger
Date: July 10, 2007 at 18:53:59 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Since you already know how to do it in bash, my recommendation would be to install cygwin and use the bash script.
http://www.cygwin.com/

Or, use a Perl or Python script.
http://activestate.com/Products/act...
http://activestate.com/Products/act...


Report Offensive Follow Up For Removal

Response Number 4
Name: giovanigonzales
Date: July 11, 2007 at 02:46:47 Pacific
Subject: .bat program to copy recursively
Reply: (edit)


thank you for the response, i tried the script and indeeed it does not recurse into source directories
so the output is:
copy file1 c:\dest\dir1file1
copy file2 c:\dest\dir1file2
copy file3 c:\dest\dir1file3
copy file1 c:\dest\dir2file1
copy file2 c:\dest\dir2file2
copy file3 c:\dest\dir2file3

i already use bash with msys from www.mingw.org , but i need to do this recursive copy a lot of times and its annoying to start msys , entering the source directory every time, etc.
a .bat script would save a lot of time

You think is possilble to make a .bat file like this?
C:\msys\1.0\msys.bat rcopy.sh

I think rsim not the first peon that needs this kind of script, any sugestion for keywords to search on google? i tried a lot of searches and now im out of ideas


Report Offensive Follow Up For Removal

Response Number 5
Name: FishMonger
Date: July 11, 2007 at 07:47:12 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

I've never used MinGW, so I don't know how much overhead it uses to load its environment, but yes, you can use a batch file as a wrapper.

However, I think it might be more efficient to use Perl. Here's a script that does what you need.

==========================================

#!perl

use strict;
use warnings;
use File::Find;
use File::Copy;

# change these assignments as needed
my $srcdir = 'C:/temp';
my $destdir = 'C:/test/folder';

finddepth(\&wanted, $srcdir);

sub wanted {
     return if -d;
     my ($file) = $File::Find::name =~ /^...(.+)$/;
     $file =~ s~/~_~g;
     copy($File::Find::name, "$destdir/$file");
}


Report Offensive Follow Up For Removal


Response Number 6
Name: giovanigonzales
Date: July 11, 2007 at 10:15:47 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Awesome!
it works really nice.
If possible, i would like some improvements:

before begining, remove all content in destination dir (like "rm -rf $dest") - with no error if it doesnt exists
create destination dir with parents if they dont exist (like "mkdir -p $dest")
can i define $srcdir as current dir? (".") I tried with $srcdir = '.'; or './' but doesnt work.
I need to run the script from the current directory and also that will remove the unnecesary prefix "temp" from the files names (considering that $srcdir="C:/temp")

muchas gracias!



Report Offensive Follow Up For Removal

Response Number 7
Name: FishMonger
Date: July 11, 2007 at 10:21:00 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Yep, those adjustments are easy. I'm just leaving for work, but I'll post back later today when I have more time.


Report Offensive Follow Up For Removal

Response Number 8
Name: FishMonger
Date: July 11, 2007 at 12:40:32 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Part of your requested adjustments implies deleting the dest dir each time the script runs. That's easy to do, but it may not be necessary.

Try this: ===========================================

#!perl

use strict;
use warnings;
use File::Find;
use File::Copy;
use File::Path;

# change these assignments as needed
my $srcdir = './';
my $destdir = 'C:/test/folder';

mkpath $destdir unless -d $destdir;
unlink <$destdir/*>;

finddepth(\&wanted, $srcdir);

sub wanted {
     return if -d;
     my ($file) = $File::Find::name =~ /^$srcdir(.+)$/;
     $file =~ s~/~_~g;
     print "Coping: $File::Find::name \n To: $destdir/$file\n";
     copy($File::Find::name, "$destdir/$file");
}


Report Offensive Follow Up For Removal

Response Number 9
Name: giovanigonzales
Date: July 11, 2007 at 13:32:43 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

now it does not copy the files from the subdirectories, but if I assign to $srcdir an absolute path (like "my $srcdir = 'C:/src';") then it works (appending an "_" as prefix to the file names)

I allways copy files to the same destination directory - from wihch i move files to final destination, and it should not be mixed with the files from previous copy, so that was really usefull - to empty it every time, thanks for that


Report Offensive Follow Up For Removal

Response Number 10
Name: FishMonger
Date: July 11, 2007 at 14:40:56 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Hmmm...I guess I should have tested after adjusting the script. It looks link there's a gotcha when using a relative path. I'll need to review the module's documentation.

If the script is in the same directory as the src files, it might be best to skip over it in the sub.

Add this return statement just after the other one in the sub.

return if $0 =~ /$_$/;

There are other improvements that I could suggest, but it all depends on what you need/want.


Report Offensive Follow Up For Removal

Response Number 11
Name: FishMonger
Date: July 11, 2007 at 14:44:17 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

>> if I assign to $srcdir an absolute path (like "my $srcdir = 'C:/src';") then it works (appending an "_" as prefix to the file names)

To get rid of the leading _ in the filename, just add the trailing / to the $srcdir i.e.,

my $srcdir = 'C:/src/';


Report Offensive Follow Up For Removal

Response Number 12
Name: giovanigonzales
Date: July 11, 2007 at 15:38:42 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Hi,
The script is named rcopy.pl and it is in the "C:\Windows\System32" directory also there i have
a rcopy.bat:
"C:\Program Files\Perl\bin\perl.exe" C:\Windows\System32\rcopy.pl
I placed them there for being in the %PATH%

Any sugestions for improvements would be nice. Maybe I will need some other things later that I dont realize now.
I added the line "return if $0 =~ /$_$/;" right after the line "copy($File::Find::name, "$destdir/$file");" but seems no difference to me


Report Offensive Follow Up For Removal

Response Number 13
Name: FishMonger
Date: July 11, 2007 at 20:26:42 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

That second return statement would only be needed if the script was in the same directory as the files that are being copied. If you do need it, it would be moved up a few lines, like this:

sub wanted {
    return if -d;
    return if $0 =~ /$_$/;
....
....
....
}

Improvements:
One of the main problems I see in a lot of scripts is the lack of error handling. A well written program (or script) would have a copious amount of error handling and in some cases the error handling would be more complex than the base code. Obviously, forums such as this are not designed to provide fully developed production level code.

2 areas of error checking that you want to consider are 1) verify that the mkpath command was successful, and 2) verify that the file copy was successful.

You may want to generate log entires at each step.

Instead of hard coding the src & dest directories, pass them as command line parameters. Print a usage statement if missing arguments or wrong type of arguments.

Add comments to any statement that may not be self explanatory.


Report Offensive Follow Up For Removal

Response Number 14
Name: Mechanix2Go
Date: July 12, 2007 at 00:44:50 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

"One of the main problems I see in a lot of scripts is the lack of error handling. A well written program (or script) would have a copious amount of error handling and in some cases the error handling would be more complex than the base code. Obviously, forums such as this are not designed to provide fully developed production level code."

Hi FM

Can I use that for my tag line?

I'll work om the bat.



=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal

Response Number 15
Name: giovanigonzales
Date: July 12, 2007 at 06:58:56 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Thanks a lot FishMonger!
The script is very usefull to me as it is now. The option to define $srcdir = "./" is not so important atm. Im using the same source dir every time. Anyways if you ever find a work around, I would be happy to see it.
Also i wont need any error handling in the forseable future as im not using the script for critical things


Report Offensive Follow Up For Removal

Response Number 16
Name: FishMonger
Date: July 12, 2007 at 10:29:12 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

giovanigonzales,

Glad I was able to help!

----------

Hi M2,

Feel free to use it as your tag line, but it's a little wordy, don't you think! :-)


Report Offensive Follow Up For Removal

Response Number 17
Name: Mechanix2Go
Date: July 16, 2007 at 05:30:51 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

It took a while to marinate.

::== recur2a.bat
@echo off
setLocal EnableDelayedExpansion

set src=c:\util
set dest=p:\stuff
pushd !src!

for /f "tokens=* delims= " %%a in ('dir/s/b/ad') do (
pushd %%a
copy . !dest! > nul 2> nul
popd
)



=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal

Response Number 18
Name: giovanigonzales
Date: July 17, 2007 at 15:18:47 Pacific
Subject: .bat program to copy recursively
Reply: (edit)


thanks, but it does not add the prefix so if there are more files with the same name in different subdirectories, it will overwrite them.
also ignores files in the src directory


Report Offensive Follow Up For Removal

Response Number 19
Name: Mechanix2Go
Date: July 21, 2007 at 05:18:42 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

I think I got it right. I put a - before filename for readability.

::== cprecur9.bat
:: lesson learned : !CD! **** note redir stderr: 2> NO SPACE
:: copy recur all files in tree to dest dir
:: prepend old dir name
:: credit to IVO for the code in :sub1

@echo off
setLocal EnableDelayedExpansion

set logdir=%CD%
set src=c:\util
set dest=p:\stuff
pushd !src!

call :sub1

for /f "tokens=* delims= " %%a in ('dir/b/a-d 2^>nul') do (
copy "%%a" "!dest!\!RD!-%%a" > nul 2> nul
)

for /f "tokens=* delims= " %%a in ('dir/s/b/ad') do (
pushd %%a
call :sub1
for /f "tokens=* delims= " %%a in ('dir/b/a-d 2^>nul') do (
copy "%%a" "!dest!\!RD!-%%a" > nul 2> nul
)
popd
)
goto :eof

:sub1

Set CF=%CD%
Set RD=
:LOOP
If "%CF:~-1,1%"=="\" GoTo :DONE
Set RD=%CF:~-1,1%%RD%
Set CF=%CF:~0,-1%
GoTo :LOOP

:DONE
goto :eof
::== done


=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal

Response Number 20
Name: giovanigonzales
Date: July 25, 2007 at 10:08:07 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

wow! the windows batch code looks defenately horrible comparing to .bash or .perl hehe
Sorry, but still the way it adds prefixes is not good, it can easily overwrite files because it does not add all the parent directories path to the prefix, only the last parent.

this is the way it works:

SRC:
dir1
  subdir1
    file1
    file2
file3.txt

result:
subdir1_file1
subdir2_file2
SRC_file3.txt

and the result should be:
dir1_subdir1_file1
dir1_subdir1_file2
file3.txt


Report Offensive Follow Up For Removal

Response Number 21
Name: Mechanix2Go
Date: July 29, 2007 at 04:12:04 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

:: copy recur all files in tree to dest dir
:: prepend old dir name

@echo off
setLocal EnableDelayedExpansion

set src=c:\files
set dest=s:\stuff
pushd !src!

for /f "tokens=* delims= " %%a in ('dir/b/a-d 2^>nul') do (
copy "%%a" "!dest!\%%a" > nul 2> nul
)

for /f "tokens=* delims= " %%a in ('dir/s/b/ad') do (
set P=%%a
set P=!P:~3,99!
set P=!P:\=_!

pushd %%a
for /f "tokens=* delims= " %%a in ('dir/b/a-d 2^>nul') do (
copy "%%a" "!dest!\!P!_%%a" > nul 2> nul
)
popd
)



=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal

Response Number 22
Name: giovanigonzales
Date: August 1, 2007 at 15:12:37 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Seems you took it as a personal chalenge heh.
Now it works fine. Thanks a lot!
Nice piece of software I would say.

Just for the sake of perfection I would point that the result is:
src_dir1_subdir1_file1
src_dir1_subdir1_file2
file3.txt

and its not suposed to prepend "src_"
and if src="c:\dir1\dir2\dir3" for example then it would prepend "dir1_dir2_dir3" to all files

Anyways the program is just perfect for me as it is now, many thanks!


Report Offensive Follow Up For Removal

Response Number 23
Name: Mechanix2Go
Date: August 2, 2007 at 01:09:31 Pacific
Subject: .bat program to copy recursively
Reply: (edit)

Glad we came out alive.


=====================================
If at first you don't succeed, you're about average.

M2



Report Offensive Follow Up For Removal






Use following form to reply to current message:

   Name: From My Computing.Net Settings
 E-Mail: From My Computing.Net Settings

Subject: .bat program to copy recursively

Comments:

 


  Homepage URL (*): 
Homepage Title (*): 
         Image URL: 
 
Data Recovery Software