Mystical_Ice
asked on
Script to copy a file to every sub-sub folder in this directory
Hi,
I have the following folder structure on a server:
c:\Users\**username**\data bases\
There are several hundred users, so there are several hundred 'username' folders, for example:
c:\users\johndoe\databases \
c:\users\marysmith\databas es\
c:\users\jamesdean\databas es\
I need to copy a file to the databases folder of each user. I would assume the path would look something like:
C:\Users\*\databases\
but i'm no good at scripting at all.
Could someone write something for me please?
MUCH appreciated!
I have the following folder structure on a server:
c:\Users\**username**\data
There are several hundred users, so there are several hundred 'username' folders, for example:
c:\users\johndoe\databases
c:\users\marysmith\databas
c:\users\jamesdean\databas
I need to copy a file to the databases folder of each user. I would assume the path would look something like:
C:\Users\*\databases\
but i'm no good at scripting at all.
Could someone write something for me please?
MUCH appreciated!
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
billprew
Insomnia??
Insomnia??
billprew
The best cure for insomnia is to get lots of sleep !!
:)
The best cure for insomnia is to get lots of sleep !!
:)
Early yet...
~bp
~bp
What's your timezone? Mine's GMT London.
US EDT (GMT-4 during daylight savings, GMT-5 in a couple of days)
~bp
~bp
ASKER
billprew -
thanks! one question though; if the file in one of the folders is in use (locked or whatever), will the script just come to a halt? How do i make it log which folder it failed at? It's going to be going through hundreds of them, and i don't want it to stop if it just fails on one
thanks! one question though; if the file in one of the folders is in use (locked or whatever), will the script just come to a halt? How do i make it log which folder it failed at? It's going to be going through hundreds of them, and i don't want it to stop if it just fails on one
listening... in case Bill not around will add you an errorlevel check in. Is this like the request I saw last night mystical_ice?
SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
I believe it will continue copying.
~bp
~bp
billprew
Incontinence?
Incontinence?
billprew
The best cure for incontinence is to get lots of sleep !!
The best cure for incontinence is to get lots of sleep !!
ASKER
Excellent! Thanks!
ASKER
Excellent, thanks!
Billprews' original comment http:#37086506 IMO would do as you asked. If you want it logged then just add > log.txt 2>&1 to the end of the line, i.e.
@echo off
(for /D %%A in ("c:\users\*") do copy "c:\temp\template.txt" "%%~A\databases") > log.txt 2>&1
If you want an actual log of error dir. names rather than going through above log would need some errorlevel checks in the individual parts of the do loop.
Steve
@echo off
(for /D %%A in ("c:\users\*") do copy "c:\temp\template.txt" "%%~A\databases") > log.txt 2>&1
If you want an actual log of error dir. names rather than going through above log would need some errorlevel checks in the individual parts of the do loop.
Steve
I did confirm, the script will continue to run even if one of the copies throws an error on afile.
~bp
~bp
Just checked prew's code and I can also confirm it will continue copying where 'Access is denied' on one or more files.
Another example of a quick errorlevel check on the code you already have from billprew might be something like this. If an error occurs it is redirected into the log file, and then the name of the offending directory too.
Steve
Steve
@echo off
del log.txt 2>NUL
for /D %%A in ("c:\users\*") do (copy "c:\temp\template.txt" "%%~A\databases")>> log.txt 2>&1 || echo ** Error with %%A -- see previous line for error ** >>log.txt
It's lengthy, but well worth it.
NOTE: Change the following line:
set source=filespec
to point to your source file/s, for example:
set source=c:\folder\file.txt or set source=c:\folder\*.txt etc...
before running the batch file.
@echo off
setlocal enabledelayedexpansion
rem Reset system error code to '0'
cmd /c exit 0
rem %source% = folder or file/s you're copying ie, c:\temp\file.tmp
rem %destination% = base location of users; folders ie, c:\users
rem %subfolder% = usres; subfolder ie, databases
rem %%a = user's folder ie, %destination%\paul - see FOR-loop below
rem Copy "%source%" "%%a\%subfolder%\" = copy "c:\temp\file.tmp" "c:\users\paul\"
rem Do not include trailing backslashes
set source=filespec
set destination=c:\users
set subfolder=databases
rem Logfile = filespec of logfile ie, c:\logs\logfile.txt
rem Tempfile = filespec of temporary file ie, %temp%\BATCHNAME.tmp
rem Where BATCHNAME is the filename of this batch file
set logfile=logfile.txt
set tempfile=%temp%\%~n0.tmp
rem Errcount = number of errors
rem Count = number of users
set errcount=0
set count=0
rem Log date and time
echo %date% %time% >>"%logfile%"
rem Check source folder or file/s exists
rem If it doesn't, set system error code '1'
if not exist "%source%" (
set errcount+=1
echo Cannot find %source%. Batch process aborted. >>"%logfile%"
cmd /c exit 1
)
rem If there's no error, continue
if %errorlevel%==0 (
rem Check destination base folder exists
rem If it doesn't, set system error code '1'
if not exist "%destination%\." (
set errcount+=1
echo Cannot find %destination% folder. Batch process aborted. >>"%logfile%"
cmd /c exit 1
)
)
rem If there's no error, continue
if %errorlevel%==0 (
rem For each user...
for /d %%a in ("%destination%\*") do (
rem Reset system error code '0'
rem Count user
cmd /c exit 0
set /a count+=1
rem Check user has target subfolder
rem If not, create it - hide system error msg
if not exist "%%a\%subfolder%\." (
md "%%a\%subfolder%\" 2>nul
rem If unable to create user's target subfolder, log it
rem Example: User Paul has no DATABASES folder.
rem System error code uneffected
if not !errorlevel!==0 (
set /a errcount+=1
echo User %%a has no %subfolder% folder. >>"%logfile%"
)
)
rem If user's target subfolder exists, copy file/s
rem Save system error msg, if any, for later use...
if !errorlevel!==0 (
copy /y "%source%" "%%a\%subfolder%\" 1>nul 2>"%tempfile%"
rem If copy unsuccessful, retrieve system error msg and log it
rem Example: Access denied... c:\users\paul
if not !errorlevel!==0 (
set /a errcount+=1
set /p errmsg=<"%tempfile%"
echo !errmsg!.. %%a >>"%logfile%"
)
)
)
echo Batch copy complete.
)
rem If all successful, report it
rem Example: File successfully copied to 25 users
if %errcount%==0 (
echo File^(s^) successfully copied to %count% user^(s^).
pause
) else (
rem Otherwise, if errors occured, report it
rem Example: 6 errors occured while copying files to 25 users.
rem Prompt user to display errors.
rem Example: Press any key to view errors
rem Open log file in Notepad
echo %errcount% error^(s^) occured while copying file^(s^) to %count% user^(s^).
set /p .=Press any key to view errors<nul
pause >nul
start /wait notepad "%logfile%"
)
rem Delete temporary file if it exists
rem Exit - remove the '/b' to close the DOS session upon exiting Notepad
del "%tempfile%" 2>nul
exit /b %errcount%
NOTE: Change the following line:
set source=filespec
to point to your source file/s, for example:
set source=c:\folder\file.txt or set source=c:\folder\*.txt etc...
before running the batch file.
@echo off
setlocal enabledelayedexpansion
rem Reset system error code to '0'
cmd /c exit 0
rem %source% = folder or file/s you're copying ie, c:\temp\file.tmp
rem %destination% = base location of users; folders ie, c:\users
rem %subfolder% = usres; subfolder ie, databases
rem %%a = user's folder ie, %destination%\paul - see FOR-loop below
rem Copy "%source%" "%%a\%subfolder%\" = copy "c:\temp\file.tmp" "c:\users\paul\"
rem Do not include trailing backslashes
set source=filespec
set destination=c:\users
set subfolder=databases
rem Logfile = filespec of logfile ie, c:\logs\logfile.txt
rem Tempfile = filespec of temporary file ie, %temp%\BATCHNAME.tmp
rem Where BATCHNAME is the filename of this batch file
set logfile=logfile.txt
set tempfile=%temp%\%~n0.tmp
rem Errcount = number of errors
rem Count = number of users
set errcount=0
set count=0
rem Log date and time
echo %date% %time% >>"%logfile%"
rem Check source folder or file/s exists
rem If it doesn't, set system error code '1'
if not exist "%source%" (
set errcount+=1
echo Cannot find %source%. Batch process aborted. >>"%logfile%"
cmd /c exit 1
)
rem If there's no error, continue
if %errorlevel%==0 (
rem Check destination base folder exists
rem If it doesn't, set system error code '1'
if not exist "%destination%\." (
set errcount+=1
echo Cannot find %destination% folder. Batch process aborted. >>"%logfile%"
cmd /c exit 1
)
)
rem If there's no error, continue
if %errorlevel%==0 (
rem For each user...
for /d %%a in ("%destination%\*") do (
rem Reset system error code '0'
rem Count user
cmd /c exit 0
set /a count+=1
rem Check user has target subfolder
rem If not, create it - hide system error msg
if not exist "%%a\%subfolder%\." (
md "%%a\%subfolder%\" 2>nul
rem If unable to create user's target subfolder, log it
rem Example: User Paul has no DATABASES folder.
rem System error code uneffected
if not !errorlevel!==0 (
set /a errcount+=1
echo User %%a has no %subfolder% folder. >>"%logfile%"
)
)
rem If user's target subfolder exists, copy file/s
rem Save system error msg, if any, for later use...
if !errorlevel!==0 (
copy /y "%source%" "%%a\%subfolder%\" 1>nul 2>"%tempfile%"
rem If copy unsuccessful, retrieve system error msg and log it
rem Example: Access denied... c:\users\paul
if not !errorlevel!==0 (
set /a errcount+=1
set /p errmsg=<"%tempfile%"
echo !errmsg!.. %%a >>"%logfile%"
)
)
)
echo Batch copy complete.
)
rem If all successful, report it
rem Example: File successfully copied to 25 users
if %errcount%==0 (
echo File^(s^) successfully copied to %count% user^(s^).
pause
) else (
rem Otherwise, if errors occured, report it
rem Example: 6 errors occured while copying files to 25 users.
rem Prompt user to display errors.
rem Example: Press any key to view errors
rem Open log file in Notepad
echo %errcount% error^(s^) occured while copying file^(s^) to %count% user^(s^).
set /p .=Press any key to view errors<nul
pause >nul
start /wait notepad "%logfile%"
)
rem Delete temporary file if it exists
rem Exit - remove the '/b' to close the DOS session upon exiting Notepad
del "%tempfile%" 2>nul
exit /b %errcount%
Wow, Paul your surpass yourself... 100 lines (no I haven't counted, it's a guess) to add error checking to a one line command....
Oh no... not the one-line-thing again...
let's see which way the hammer swings - i will say though, i don't feel optimistic!
a great solution can be found at http:#37087454
let's see which way the hammer swings - i will say though, i don't feel optimistic!
a great solution can be found at http:#37087454
SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
Just spotted two small errors in my code above (http:#37091887).
Two lines need editing. The dots need to be removed:
if not exist "%destination%\." (
should be:
if not exist "%destination%\" (
if not exist "%%a\%subfolder%\." (
should be:
if not exist "%%a\%subfolder%\" (
because they won't correctly test for the existence of folders if the dots are not removed.
Two lines need editing. The dots need to be removed:
if not exist "%destination%\." (
should be:
if not exist "%destination%\" (
if not exist "%%a\%subfolder%\." (
should be:
if not exist "%%a\%subfolder%\" (
because they won't correctly test for the existence of folders if the dots are not removed.
Ironic.
billprew...
Looking at your code (http:#37093523). On the subject of validation, line 20:
if not exist "%%~A\%DestDir%\" md "%%~A\%DestDir%\"
could fail and is no more a certainty as:
md "%%~A\%DestDir%\" 2>nul
by itself.
Given the above is true, then both lines 23 and 24:
copy /Y "%CopyFile%" "%%~A\%DestDir%">>"%LogFil e%" 2>>&1 || (
echo %%~A\%DestDir% - Copy failed, see log file>>"%FailFile%"
)
could also fail.
Just an observation and most probably unlikely to be of any real concern (here) - unless of course it was written for a mission-critical process such as air-traffic control systems, long-range missile guidance systems or nuclear core reaction control systems (under which case, one of Steve's one-liners would definitely not be appropriate even under the most austere measures).
Looking at your code (http:#37093523). On the subject of validation, line 20:
if not exist "%%~A\%DestDir%\" md "%%~A\%DestDir%\"
could fail and is no more a certainty as:
md "%%~A\%DestDir%\" 2>nul
by itself.
Given the above is true, then both lines 23 and 24:
copy /Y "%CopyFile%" "%%~A\%DestDir%">>"%LogFil
echo %%~A\%DestDir% - Copy failed, see log file>>"%FailFile%"
)
could also fail.
Just an observation and most probably unlikely to be of any real concern (here) - unless of course it was written for a mission-critical process such as air-traffic control systems, long-range missile guidance systems or nuclear core reaction control systems (under which case, one of Steve's one-liners would definitely not be appropriate even under the most austere measures).
@paultomasi
It's my training I guess, I typically avoid coding in such a manner that allows for errors as "acceptable". To me that's what this approach involves:
md "%%~A\%DestDir%\" 2>nul
Essentially it says try the MD and if errors are thrown, it's okay. And the errors or lost forever.
I prefer the more explicit approach which only executes the MD if it is needed. In this manner, if an error is thrown, we want to know about it (permission, bad path, etc).
This is why I typically do this:
if exist log.txt del log.txt
rather than just:
del log.txt>nul 2>nul
For me it's more obvious what the code is doing to the next person reading it, and it at least allows for an error message to be displayed or trapped (if the whole output of the BAT file were redirected for example).
I agree that AFTER either MD it would be best practice to check for the existence of the directory (or trap errors from the MD command) and potentially not continue if they occur. Most BAT files I see proposed (and accepted) here though aren't looking for this type of error checking, but are rather looking for quick and easy solutions to small problems.
Hope that makes sense, let me know if it didn't.
~bp
It's my training I guess, I typically avoid coding in such a manner that allows for errors as "acceptable". To me that's what this approach involves:
md "%%~A\%DestDir%\" 2>nul
Essentially it says try the MD and if errors are thrown, it's okay. And the errors or lost forever.
I prefer the more explicit approach which only executes the MD if it is needed. In this manner, if an error is thrown, we want to know about it (permission, bad path, etc).
This is why I typically do this:
if exist log.txt del log.txt
rather than just:
del log.txt>nul 2>nul
For me it's more obvious what the code is doing to the next person reading it, and it at least allows for an error message to be displayed or trapped (if the whole output of the BAT file were redirected for example).
I agree that AFTER either MD it would be best practice to check for the existence of the directory (or trap errors from the MD command) and potentially not continue if they occur. Most BAT files I see proposed (and accepted) here though aren't looking for this type of error checking, but are rather looking for quick and easy solutions to small problems.
Hope that makes sense, let me know if it didn't.
~bp
<<air-traffic control systems, long-range missile guidance systems or nuclear core reaction control systems >>
@Paultomasi: Agreed. I would hope such systems aren't written by taking snippets of batch files from free answers on Experts Exchange :-)
An yes I am quite aware of how to make bullet prooof, error checked, debugged code when needed!
I also know when it is appropriate to write a one line command, or short batch file it when it is needed. You may want to stand back and look at http:#37093523 or http:#37086506, or indeed your own http:#37086521 and compare with the amount of code to maintain and debug in http:#37091887
Steve
@Paultomasi: Agreed. I would hope such systems aren't written by taking snippets of batch files from free answers on Experts Exchange :-)
An yes I am quite aware of how to make bullet prooof, error checked, debugged code when needed!
I also know when it is appropriate to write a one line command, or short batch file it when it is needed. You may want to stand back and look at http:#37093523 or http:#37086506, or indeed your own http:#37086521 and compare with the amount of code to maintain and debug in http:#37091887
Steve
ASKER
Thanks so much for the help. billprew, since you answered my original question, i have to give by far the majority of points to you.
paul, i appreciate your help as well. just chill a little bit :)
paul, i appreciate your help as well. just chill a little bit :)
@Mystical_Ice
Glad that turned out to be useful, thanks for the feedback.
~bp
Glad that turned out to be useful, thanks for the feedback.
~bp
Open in new window
or this as a command in DOS:Open in new window
If you don't want output to the screen add '>nul' to the end of the line like this:Open in new window
Or like this:Open in new window