Link to home
Start Free TrialLog in
Avatar of Mystical_Ice
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**\databases\

There are several hundred users, so there are several hundred 'username' folders, for example:
c:\users\johndoe\databases\
c:\users\marysmith\databases\
c:\users\jamesdean\databases\

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
Avatar of Bill Prew
Bill Prew

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
if your file is named FILE.TXT then you can do this in a batch file:
@echo off
for /d %%a in ("c:\users\*") do copy /y FILE.TXT "%%a\databases\"

Open in new window

or this as a command in DOS:
for /d %a in ("c:\users\*") do @copy /y FILE.TXT "%a\databases\"

Open in new window

If you don't want output to the screen add '>nul' to the end of the line like this:
@echo off
for /d %%a in ("c:\users\*") do copy /y FILE.TXT "%%a\databases\" >nul

Open in new window

Or like this:
for /d %a in ("c:\users\*") do @copy /y FILE.TXT "%a\databases\" >nul

Open in new window

billprew

Insomnia??
billprew

The best cure for insomnia is to get lots of sleep !!

:)
Avatar of Bill Prew
Bill Prew

Early yet...

~bp
What's your timezone? Mine's GMT London.
US EDT (GMT-4 during daylight savings, GMT-5 in a couple of days)

~bp
Avatar of Mystical_Ice

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
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
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I believe it will continue copying.

~bp
billprew

Incontinence?
billprew

The best cure for incontinence is to get lots of sleep !!
Excellent! Thanks!
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
I did confirm, the script will continue to run even if one of the copies throws an error on afile.

~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
@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

Open in new window

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%
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
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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%">>"%LogFile%" 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).
@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
<<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
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 :)
@Mystical_Ice

Glad that turned out to be useful, thanks for the feedback.

~bp