Computer Hope

Microsoft => Microsoft DOS => Topic started by: nothlit on January 22, 2009, 10:41:41 AM

Title: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 22, 2009, 10:41:41 AM

I have a batch file that is coping directories from a network path to another network path and in most cases I am coping about 300 files which can take a good 10 minutes. What I want to do is have something display on the screen that says Working . a few moments later Working .. and a few moments later Working ... that then maybe resets after 10 . or something. I have come across some bits of code but not really what I am looking for.


Excerpt of my current code ...
Code: [Select]
Goto :Xcopy1

:Xcopy1
rem Pause & Echo Check folder structure for correct number of files & Rem ECHO Type 'D' if asked for directory or file? & sleep 3
Echo Working ...
Echo.>>%log%
Echo **********XCOPY START %Time%**********>>%log%
xcopy %DevelopHost%\bank\T%CN%\Parms %ProductionSrv%\bank\T%CN%\Parms /Y>>%log%

Rem Xcopy Parms and Forms from IRDTEMPLATE
cls
Echo Working ...
Echo.>>%log%
Echo **********XCOPY Parms/Forms from IRDTEMPLATE**********>>%log%
xcopy %ProductionSrv%\irdimagetemplates\Parms %ProductionSrv%\bank\T%CN%\Parms /Y>>%log%
Echo.>>%log%
rem md %ProductionSrv%\bank\T%CN%\Forms
Echo D | xcopy %ProductionSrv%\irdimagetemplates\Forms %ProductionSrv%\bank\T%CN%\Forms /Y>>%log%
Echo.>>%log%
Echo D | xcopy %ProductionSrv%\bank\T%CN%\Forms %ProductionSrv%\bank\%CN%\Forms /Y>>%log%
Echo **********XCOPY for T%CN% Finished %M%/%D%/%Y% %Time%**********>>%log%
Rem Delete Date.ctl
cd\
Y:
cd bank\T%CN%\Parms
Echo Deleting Date.ctl from %ProductionSrv%\bank\T%CN%\Parms>>%log% & Del /P Date.ctl & Echo Date.ctl deleted & Sleep 2


Examples of code I have found ... (Might be useful for others on other things, seems pretty cool)
Code: [Select]
@ECHO OFF
set "max=11"
call :initProgress %max% "Window Title: [PPP]"
for /l %%N in (1,1,%max%) do (
    ping -n 2 -w 1 127.0.0.1>NUL
    call:doProgress
)
GOTO:EOF

:initProgress max format -- initialize an internal progress counter and display the progress in percent
::                       -- max    [in]     - progress counter maximum, equal to 100 percent
::                       -- format [in,opt] - title string formatter, default is '[P] completed.'
:$created 20060101 :$changed 20080327
:$source http://www.dostips.com
set /a "ProgressCnt=-1"
set /a "ProgressMax=%~1"
set "ProgressFormat=%~2"
if not defined ProgressFormat set "ProgressFormat=[PPPP]"
set "ProgressFormat=%ProgressFormat:[PPPP]=[P] completed.%"
call:doProgress
EXIT /b


:doProgress -- display the next progress tick
:$created 20060101 :$changed 20080327
:$source http://www.dostips.com
set /a "ProgressCnt+=1"
SETLOCAL ENABLEDELAYEDEXPANSION
set /a "per100=100*ProgressCnt/ProgressMax"
set /a "per10=per100/10"
set /a "per10m=10-per100/10-1"
set "P=%per100%%%"
set "PP="
for /l %%N in (0,1,%per10%) do call set "PP=%%PP%%*"
for /l %%N in (%per10%,1,9) do call set "PP=%%PP%% "
set "PPP="
for /l %%N in (0,1,%per10m%) do call set "PPP=%%PPP%%*"
set "ProgressFormat=%ProgressFormat:[P]=!P!%"
set "ProgressFormat=%ProgressFormat:[PP]=!PP!%"
set "ProgressFormat=%ProgressFormat:[PPP]=!PPP!%"
title %ProgressFormat%
EXIT /b



Code: [Select]
REM http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/Q_23923370.html

@echo off
setlocal enabledelayedexpansion
echo.
echo.
set i=1
cls
(Set /P j=Running the command) < NUL
ECHO.
echo.

FOR /l %%a in (1,1,79) do set j=!j!²
FOR /l %%a in (1,1,79) do set j=!j!
(Set /P j=!j!) < NUL

:start
call :show %i%

:put the command in the next line
ping -n 1 127.0.0.1 > NUL

set /a i = i + 1
if /i %i% leq 79 goto start
ECHO.
ECHO.
(Set /P j=End) < NUL
ECHO.
PAUSE>NUL
goto :EOF
 
:show
(Set /P j=Û) < NUL
set /a p=(%1*100)/79
title !p!%% Done
exit /b
endlocal


Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 22, 2009, 10:45:36 AM
I don't if something like below would be a start or not, but I was playing with this to see if I can xcopy a single file from the dir command, but didn't get very far with that process. Thanks for anyones help or advise. :)

Code: [Select]
rem @echo off
set wkdir=%cd%\workdir
setlocal enabledelayedexpansion
md "%wkdir%"

pushd %wkdir%
Set /a count=0
for /f "tokens=1 delims=" %%A in ('dir /b /a:-d /o:-d 2^>NUL') do call :PROCESS "%%A"
echo %%A
popd
goto :end

:PROCESS
set /a count+=1

Echo %%A & pause
goto :eor
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Helpmeh on January 22, 2009, 02:58:22 PM
To answer your first post, you can't do that while still doing another command (XCOPY for example).

To do that sort of thing without another command executing at the same time, use ping.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 22, 2009, 03:51:13 PM
Is there a way to use a For loop to xcopy one file at a time thus in between echoing Working . or Working .. etc.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Helpmeh on January 22, 2009, 04:11:08 PM
That should be possible, I'm not good with FOR so I can't help...sorry :-[
Title: Re: XCOPY ---- Progress Display ... ?
Post by: BatchFileCommand on January 22, 2009, 04:37:07 PM
Or if you just want to keep it simple you could just make another batch file with the working. thing. Then just call that batch file.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Helpmeh on January 22, 2009, 04:38:09 PM
But call won't continue the first batch untill the other is done.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: BatchFileCommand on January 22, 2009, 04:48:54 PM
Hm, forgot about that.....Screw that then.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 22, 2009, 04:50:36 PM
It's true that once XCOPY starts executing control will not be given over to another process. If you can dumb down XCOPY to COPY, you can this show this primitive progress bar between copy operations:

Code: [Select]
@echo off
for /f "tokens=* delims=" %%x in ('dir /a-d /s /b drive:\source') do (
<nul set/p z= .
copy %%x drive:\target > nul
        >nul ping localhost -n 2 
  )

Change drive:\source and drive:\target as required. The ping is not required. Used for eye candy. The progress bar shows dots in this example, but that too can be changed.

 8)
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 23, 2009, 08:18:48 AM
Ok I came up with this, thanks Sidewinder ...

Code: [Select]
@echo off
set wkdir=%cd%\workdir
set dest=%cd%\dest
setlocal enabledelayedexpansion
md "%wkdir%"


pushd %wkdir%
rem Set /a count=0
cls
for /f "tokens=* delims=" %%A in ('dir /b /a:-d /o:-d 2^>NUL') do (
rem set /a count+=1
<nul set /p z= .
Echo F | xcopy "%wkdir%\%%A" "%dest%\%%A" > nul
rem >nul ping localhost -n 2
rem Echo %%A & pause
)
popd
ping localhost -n 5 >nul
Echo end & pause

Looks like my problem before was calling another process to do the xcopy ... didn't realize that calling another process doesn't keep the VAR %%A

Sidewinder ... what is the point of this?
Code: [Select]
<nul set /p z= .
Ok I get it displays '.' on the screen each time we go through the for loop, but wouldn't Echo . produce the same results, just trying to understand why you have it this way instead. Thanks again for your reply and help.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 23, 2009, 11:44:36 AM
Using the echo command would produce a series of vertical dots as echo adds a carriage return/line feed after the echoed text.

This particular set command prompts the user with a dot prompt and automatically responds with nul input (no carriage control/line feed). By doing so, the cursor remains on the same line when it executes the set the next time thru the loop.

I found this in my world famous snippet closet under too smart by half. ;D

If you really want to show off, you could determine how many files were to be processed and then incoporate something like this (replacing the 20 with a variable of course):

Code: [Select]
@echo off
for /l %%x in (20, -1, 0) do (
   <nul set/p z= %%x
   >nul ping localhost -n 2 
  )

Good luck.  8)
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 23, 2009, 12:25:32 PM
Ok this is what I have and I know why it won't work because of how I have the For loops set up, but don't know how to fix it ....

Code: [Select]
@echo off
set wkdir=%cd%\workdir
set dest=%cd%\dest
setlocal enabledelayedexpansion
md "%wkdir%"


pushd %wkdir%
Set /a count=0
cls

Echo Counting ... & ping localhost -n 3 >nul & cls

for /f "delims=" %%a in ('dir /b /a:-d /o:-d 2^>NUL') do call :PROCESS "%%a"
popd
goto :end

:PROCESS
set /a count+=1
rem Echo  File Count in %wkdir% is %Count%
goto :eor
:end
Echo  Final File Count in %wkdir% is %Count% & pause

pushd %wkdir%
cls

Echo Start & Echo.


for /f "tokens=* delims=" %%A in ('dir /b /a:-d /o:-d 2^>NUL') do (


for /l %%x in (%count%, -1, 0) do (
    <nul set/p z= %%x
Echo F | xcopy "%wkdir%\%%A" "%dest%\%%A" > nul
    >nul ping localhost -n 2 
  )
)
popd

ping localhost -n 5 >nul
Echo. & Echo end & pause

Basically the way it is working I think I need to reorder something or change how I count the files. Maybe I'm just tired and have been looking at it too long. Whatever the case can you take a look and see how to reorder organize ... I think I like the idea of counting down.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 23, 2009, 02:47:15 PM
There is some code I'm not understanding. You make a directory, push to make it the current directory, then run a dir list on it? Would the directory be empty? When testing I had workdir full of files and copied them to dest.

When nesting loops, the innermost runs to completion before the top loop cycles again. There is no :eor label for the goto (typo?).

Batch files should be sleek and productive. The baseline here is a copy operation. The rest is bells and whistles that add a cuteness factor. I give it a 8.3  ;D

Think of this example as the lite-version of your code.

Code: [Select]
@echo off
set wkdir=%cd%\workdir
set dest=%cd%\dest
if not exist "%wkdir%" md "%wkdir%"
pushd %wkdir%

:: Get Number of Files in Dir
for /f "tokens=1*" %%i in ('dir /a:-d ^| find /i "file(s)"') do set count=%%i

echo Start Copy Operation
:: Copy Files; Show Progress
for /f "delims=" %%a in ('dir /b /a:-d /o:-d') do (
<nul call set/p z= %%count%%
        copy "%wkdir%\%%a" "%dest%\%%a" > nul
  >nul ping localhost -n 2 
  set /a count-=1
)
popd
echo.
echo End Copy Operation

Happy coding.  8)
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 23, 2009, 03:12:38 PM
There is some code I'm not understanding. You make a directory, push to make it the current directory, then run a dir list on it? Would the directory be empty? When testing I had workdir full of files and copied them to dest.

When nesting loops, the innermost runs to completion before the top loop cycles again. There is no :eor label for the goto (typo?).

Happy coding.  8)

MD ... Your right I made the directory as this is a lite version of a version of xcopy I already use so I basically just pulled some of the code out so I could get some advice. :) I am doing a directory listing to run a counter on the number of files in the directory tree. When coping from Network folder to Network folder I might have some 300 plus files which can take a long time so the whole point of this is to make it so the user knows that the process is still running without having to go to the server to verify files are still being copied in ... most users wouldn't know how to do that anyway.

:EOR ... when I was originally coding this if I had a real label it wouldn't work right it would exit out or something, didn't take notes just know that by having it goto no where it would stay in the loop to count the number of files.


Ok ... now that I've said this I will read the code and let you know what I think.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 23, 2009, 03:26:45 PM
Code: [Select]

<nul call set/p z= %%count%%
       
  >nul ping localhost -n 2 
 
   

What is the difference between <nul & >nul> ... is this the same thing as ping localhost -n 2 >nul?  I have never seen >nul first, I know when put at the end it sends it to nothing or not to console and it appears putting in front does the same thing ... just curious.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 23, 2009, 03:48:28 PM
Input:
Code: [Select]
<nul

Output:
Code: [Select]
>nul

Quote
Ok ... now that I've said this I will read the code and let you know what I think.

<sigh> I gotta talk to Nathan about that raise. ;D

PS. The code will not work if you insist on using XCOPY. You're not using any switches that are unique to XCOPY, so COPY is actually a better choice.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 23, 2009, 03:51:16 PM

PS. The code will not work if you insist on using XCOPY. You're not using any switches that are unique to XCOPY, so COPY is actually a better choice.


Didn't think copy worked correctly over network drives? Maybe it would work by using Pushd, this is a new command I found, from what i have read creates a temporary drive until you popd it off ...
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 23, 2009, 04:51:37 PM
Completed product with COPY for now ... going to play with xcopy later ... Why do you say xcopy won't work?  Thank you very much for all your effort put forth into this, a raise would be a wonderful thing. :)

Code: [Select]
@echo off
set wkdir=%cd%\workdir
set dest=%cd%\dest

set perc=0

setlocal enabledelayedexpansion

if not exist "%wkdir%" md "%wkdir%"

pushd %wkdir%

:: Get Number of Files in Dir

for /f "tokens=1*" %%i in ('dir /a:-d ^| find /i "file(s)"') do set count=%%i

set storcount=%count%


Title 0%% Done

echo Start Copy Operation
Echo.
Echo The numbers printed to screen represent the number of files left to copy
Echo.
:: Copy Files; Show Progress

For /f "delims=" %%a in ('dir /b /a:-d /o:-d') do (

<nul call set/p z= !count!
        copy "%wkdir%\%%a" "%dest%\%%a" > nul
  rem >nul ping localhost -n 2 
 
set /a count-=1


set /a perc+=1


set /a p=(!perc!*100^)/%storcount% >>log.log


title !p!%% Done
)

popd
echo.
echo End Copy Operation & pause >nul
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 23, 2009, 05:09:39 PM
Quote
Why do you say xcopy won't work?

I may have misspoke. There goes my raise! You're only feeding one file at a time to XCOPY so I'm guessing COPY and XCOPY will work same.

Quote
Didn't think copy worked correctly over network drives?

Where did you here this? I've never had any problems with copy over a network using either UNC notation or mapping the drive. My only experience with PUSHD and the flipside POPD as been to put directory names on the stack for future retrieval. Learn something new everyday. :)
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 26, 2009, 09:03:45 AM
Sidewinder, I was hoping I could pick your brain one more time. I added some code and seem to have broken what I had, thought I found my mistake, but the batch file is still crashing. Here is the code ....


Part of what I added ... I like the output to the screen, but as I get to double/single digits the display starts to look look off. I wanted to count the number of CHAR in the Count VAR to determine if it was 1, 2, or 3 char long then output accordingly by adding a leading zero to the number when it outputted to the console.


I used this code before to do a count, but never in a For loop ... maybe that is my problem. I found a couple mistakes so maybe there is something I am missing. Thanks again for your help. :) At this rate I might have to pay your raise.

Code: [Select]
:LOOP_0
IF "!counter!"=="" GOTO :RESULT
SET /a strgCount+=1
SET counter=%counter:~1%
GOTO :LOOP_0

:RESULT

The whole thing

Code: [Select]
ECHO on
set wkdir=%cd%\workdir
set dest=%cd%\dest

set perc=0
set counter=0
SET strgCount=0

setlocal enabledelayedexpansion

if not exist "%wkdir%" md "%wkdir%"



Rem  Get Number of Files in Dir

pushd %wkdir%
for /f "tokens=1*" %%i in ('dir /a:-d ^| find /i "file(s)"') do set count=%%i

Rem Store number of files for Percentage completion tracking
set storcount=%count%
Title 0%% Done

ECHO Start Copy Operation
ECHO.
ECHO The numbers printed to screen represent the number of files left to copy
ECHO.

REM Copy Files Show Progress


For /f "delims=" %%a in ('dir /b /a:-d /o:-d') do (

set counter=!count!
SET strgCount=0

:LOOP_0
IF "!counter!"=="" GOTO :RESULT
SET /a strgCount+=1
SET counter=%counter:~1%
GOTO :LOOP_0

:RESULT


if "!strgcount!"=="3" Goto pass1
Goto check1
:pass1
<nul call set/p z= !count! & goto copypro
:Check1
if "!strgcount!"=="2" Goto pass2
Goto check2
:pass2
<nul call set/p z= 0!count! & goto copypro
:Check2
if "!strgcount!"=="1" Goto pass3
Goto check3
:pass3
<nul call set/p z= 00!count! & goto copypro

:Check3
:copypro
        copy "%wkdir%\%%a" "%dest%\%%a" > nul
 
set /a count-=1
set /a perc+=1

Rem Changes title to ^%Percentage
set /a p=(!perc!*100^)/%storcount%

title !p!%% Done
)

popd

ECHO.
ECHO End Copy Operation & pause >nul
Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 26, 2009, 01:13:56 PM
Quote
At this rate I might have to pay your raise.

You can't afford me. ;D Either can Nathan, but I haven't told him yet.

Quote
Part of what I added ... I like the output to the screen, but as I get to double/single digits the display starts to look look off. I wanted to count the number of CHAR in the Count VAR to determine if it was 1, 2, or 3 char long then output accordingly by adding a leading zero to the number when it outputted to the console

What happens if the last count on the line wraps to the next line?

This is some generic code I found. Works for three digits. I'll let you incorporate it into your code.

Code: [Select]
@echo off
setlocal
:loop
call set chr=%%count:~%len%, 8192%%
if "%chr%"=="" goto exit
set /a len+=1
goto loop

:exit
if %len% EQU 1 set count=00%count%
if %len% EQU 2 set count=0%count%
echo %count%

Good luck.  8)

You can remove the setlocal statement. I used it for testing purposes. The 8192 is the max size of the environment on a XP machine. You can reduce this in keeping with your needs. Five would be a good choice for future expansion.
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 26, 2009, 01:39:42 PM
Question ... does doing a loop without the call procedure throw yourself out of the normal for loop operation ... is that what I was doing wrong?
Title: Re: XCOPY ---- Progress Display ... ?
Post by: hiteshsavla on January 26, 2009, 02:50:22 PM
This is pretty good. :)

Just a thought - How can this be made to work for recursive copying. What if wkdir has subdirectories in it?

I am sorry to put in a question of my own within this conversation. If you want me to open a new topic, would be glad to do that too. However I thought since this is an active topic, I will just post my question here.

Title: Re: XCOPY ---- Progress Display ... ?
Post by: Sidewinder on January 26, 2009, 03:12:29 PM
Notice I didn't try to incorporate the snippet into your code. I was afraid the whole thing would fall apart. :D

Why not use the call instruction to transfer control to an internal subroutine? You can format the count immediately prior to writing on the console?

Quote
Question ... does doing a loop without the call procedure throw yourself out of the normal for loop operation

I think the fact of a :label within the for loop is creating unpredictable results. I'm not certain how the interpreter keeps track of the return addresses.

How did a seemingly simple copy operation turn into such a Rube Goldberg contraption? Batch code is NOT a programming language.

 8)

If the KISS recruiter needs applicants, he should lurk in the DOS alley.

@hiteshsavla
Quote
Just a thought - How can this be made to work for recursive copying. What if wkdir has subdirectories in it?
If this refers to your other post (http://www.computerhope.com/forum/index.php/topic,70998.msg493049.html#msg493049), don't even think it.  ;D
Title: Re: XCOPY ---- Progress Display ... ?
Post by: nothlit on January 26, 2009, 03:48:26 PM
Notice I didn't try to incorporate the snippet into your code. I was afraid the whole thing would fall apart. :D

Your right, it fell apart ... I guess I have never run into trying to do something in a FOR loop before. :P ... I guess I confused how to continue then. I guess the whole effort is just make the display on the screen more in line, as the numbers get small they start to get out of line and I no longer have pretty columns ... Love the bit of code
Code: [Select]
<nul call set /p z= !count! much better then echo

My problem is by calling a routine I end up getting it to work again, but get a message that echos 'The system cannot find the batch label specified -'

This bit of code was purely to make the display nicer ...
Code: [Select]
if %len% EQU 1 set count=00%count%
if %len% EQU 2 set count=0%count%

Quote


How did a seemingly simple copy operation turn into such a Rube Goldberg contraption? Batch code is NOT a programming language.

 

Your right it isn't a batch language, but i'm amazed everyday I learn something new that it can do :D, thanks for all your help.