Batch file copying script giving errors on for loop - scripting

I'm in the middle of writing a batch script that will copy a bunch of tiny files from one location to another, verify that the file exists in the new directory, delete the original, and move on. I've implemented a FOR loop to do this, but I can't seem to get it working. Any ideas?
::Copying files-
::For loop copies file, verifies file was copied,
::and removes file from source.
for %%f in (Q:%source%\*) do (
:recopy
copy %%f %dest%\%%f
if not exist %dest%\%%f goto recopy
set /a count+=1
del %source%\%%f
echo copied !count! of %total%
ping -n 1 -w 500 1.1.1.1 >nul
)
The inputs for the variables are as follows:
set /P source=Enter path to files on P:(Temp) drive (EX: jdoe\copy)
set dest=D:Temp\Copy
Scripted adding if network share is as follows:
net use Q: \\SERVER\Temp
The error given is:
The system cannot find the file specified
and the error is repeated until the screen fills.
Full pastebin at http://pastebin.com/yjXP7H6U

You can't have a label within a for loop or if statement if memory serves. You should move :recopy outside the loop. Something like this:
::Copying files-
::For loop copies file, verifies file was copied,
::and removes file from source.
for %%I in (Q:\%source%\*) do (
call :recopy "%%~fI" "%dest%\%%~nxI"
set /a count+=1
del "%%~fI"
echo copied !count! of %total%
ping -n 1 -w 500 1.1.1.1 >nul
)
goto :EOF
:recopy source dest
copy "%~1" "%~2"
if not exist "%~2" call :recopy "%~1" "%~2"
goto :EOF

Related

Search a string inside a spooled text file in BAT file

I am a complete beginner in bat files. I am explaining the scenario of mine requirement. Hope I will get the exact o/p from you gurus.
This is my current batch file:
Note : findstr command specified by OP in comment included in code but spacing - well, who knows? OP to edit, please
CALL %ORACLE_HOME%/bin/sqlplus "/as sysdba" #D:\Long_Running\Long_running_job.sql > D:\Long_Running\LongrunningJobs.txt
call :CheckEmpty "%file%"
powershell -ExecutionPolicy ByPass -File D:\Long_Running\Send_email_report.ps1
goto :eof
:CheckEmpty
if %~z1 == 0 exit
This basically connects SQL plus, connects as sysdba, go to location where Long_running.sql file is present and spools the o/p to LongrunningJobs.txt.
From there it triggers mails in the next line(power shell).
Requirement: If I can search for a particular string say "ABCDE" in the LongrunningJobs.txt file and if it matches then it should trigger the mail else it should not trigger mail and simply come out.
What exactly should I input? I used FINDSTR might be I didn't use it correctly, it did not go well. The mail was not triggered.
#ECHO OFF
SETLOCAL
SET "destdir=U:\destdir"
SET "outfile=%destdir%\LongrunningJobs.txt"
:: first test : empty file
COPY /y NUL "%outfile%" >NUL 2>NUL
ECHO test 1
FINDSTR "ABCDE" "%outfile%" >NUL &&ECHO Send mail
:: second test : file NOT containing "ABCDE"
ECHO something >"%outfile%"
ECHO test 2
FINDSTR "ABCDE" "%outfile%" >NUL &&ECHO Send mail
:: third test : file containing "ABCDE"
ECHO ABCDE>>"%outfile%"
ECHO test 3
FINDSTR "ABCDE" "%outfile%" >NUL &&ECHO Send mail
GOTO :EOF
I use destdir to keep from cluttering my system.
Note that send mail will only be echoed in the third case, where the subject file contains the target string.
FINDSTR "ABCDE" "%file%" >NUL && (
powershell -ExecutionPolicy ByPass -File D:\Long_Running\Send_email_report.ps1
goto :eof )
#Magoo has given the correct answer, I was calling the function which i should not have. Thanks a lot everyone.

Grouping files and 'splitting' by number and copying them inside folders

I have 5000+ files inside a directory.
I want to manage these files 'splitting' every 500 files so first pack is copied inside folder1, pack2 of other 500 files is copied in folder2 and so on.
Which .bat script can I use ?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
SET /a destcount=0
SET /a maxcount=5
SET /a filecount=maxcount
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
SET /a filecount +=1
IF !filecount! geq %maxcount% (
SET /a filecount=0
SET /a destcount +=1
MD "%destdir%\folder!destcount!"
)
ECHO(COPY "%sourcedir%\%%a" "%destdir%\folder!destcount!\"
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
maxcount sets the number of files to assign to a group.
The required COPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(COPY to COPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)
Essentially, count the number of transfers and increment the destination-directoryname each time a group is complete, using delayedexpansion to access the run-time values of the counters

Batch command to check for partial filename then move

I'm in need of a batch command that will look into a directory's sub folders and find a partial file name. If that file exists, then move that directory otherwise leave it alone.
I have a folder full of movies:
D:\Movies\movie1\
\movie2\
\movie3\
Within each movie folder I would like to know if it has a trailer downloaded into the folder, if so then move that directory to x:\movies. I say partial file name as every trailer file will include the title of the movie with "-trailer" added to the end (f.e. The Interview (2014)-trailer).
Let's look for a solution from Windows CLI (Command Line Interpreter) with -> prompt using An A-Z Index of the Windows CMD command line and with next scenario:
->tree d:\test\movies
D:\TEST\MOVIES
├───movie1
├───movie2
├───movie3
└───movie4
->tree d:\test\xmovies
D:\TEST\XMOVIES
No subfolders exist
->dir /B /S /A-D "d:\test\movies"
d:\test\movies\movie1\The View (2014)-trailer missing.rtf
d:\test\movies\movie2\The Interview (2014)-trailer.bat
d:\test\movies\movie2\The Interview (2014)-trailer.bmp
d:\test\movies\movie2\The Interview (2014)-trailer.txt
d:\test\movies\movie3\An Interview (2014)-trailer.bmp
To find all those files under MOVIES subfolder with -trailer added to the filename end preceding . of file extension:
->dir /B /S /A-D "d:\test\movies\*-trailer.*"
d:\test\movies\movie2\The Interview (2014)-trailer.bat
d:\test\movies\movie2\The Interview (2014)-trailer.bmp
d:\test\movies\movie2\The Interview (2014)-trailer.txt
d:\test\movies\movie3\An Interview (2014)-trailer.bmp
To get folder names only:
->for /F "tokens=*" %G in ('dir /B /S /A-D "d:\test\movies\*-trailer.*"') do #echo %~dpG
d:\test\Movies\movie2\
d:\test\Movies\movie2\
d:\test\Movies\movie2\
d:\test\Movies\movie3\
But here the movie2 appears more than once! And, moreover, the move command does not allow source directory with trailing backslash:
->move "D:\test\Movies\movie4\" "D:\test\xMovies\"
The system cannot find the file specified.
->move "D:\test\Movies\movie4" "D:\test\xMovies\"
1 dir(s) moved.
Therefore we need switch from Windows shell (CLI) to batch scripting. Create file 28167824.bat (e.g with notepad and save it to D:\bat\StackOverflow folder):
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
for /F "tokens=*" %%G in (
'dir /B /S /A-D "d:\test\movies\*-trailer.*"'
) do (
set "rawfolder=%%~dpG"
if exist "%%~dpG" call :moveDir
)
:endlocal
#ENDLOCAL
goto :eof
:moveDir
set "srcfolder=%rawfolder:~0,-1%"
`enter code here`echo move "%srcfolder%" "d:\test\xMovies\"
rem move "%srcfolder%" "d:\test\xMovies\"
goto :eof
Run this batch script, the template of next move commands is the same as in that successful move command mentioned above:
->D:\bat\StackOverflow\28167824
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie3" "d:\test\xMovies\"
Bingo! Now we could remove rem before move "%srcfolder%" "d:\test\xMovies\", save the script and run it:
->D:\bat\StackOverflow\28167824
move "d:\test\Movies\movie2" "d:\test\xMovies\"
1 dir(s) moved.
move "d:\test\Movies\movie3" "d:\test\xMovies\"
1 dir(s) moved.
And here is final configuration, cf. starting scenario:
->tree d:\test\movies
D:\TEST\MOVIES
└───movie1
->tree d:\test\xmovies
D:\TEST\XMOVIES
├───movie2
├───movie3
└───movie4

Saving Number of Lines in File as a Variable in Batch File

I have this really nice line in my batch file that tells me how many lines are in a file:
find /v /c "" C:\Users\c1921\mypath\myfolder\!$Unit!.txt
This is nice and gives me 31 for the particular file I'm working with. My problem is the file looks something like this:
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
my_handled
219278
check
219276
control
219274
I want to be able to skip the first three lines entirely and then save the first value and then use the second value in my next command etc.
How do I save the number (e.g. 31) into a variable in my batch file?
On a hunch I tried setting a variable like so but it wasn't effective:
set "$testVar="""
echo !$testVar!
This command allows you to "save the number (e.g. 31) into a variable in my batch file":
for /F %%a in ('find /v /c "" ^< C:\Users\c1921\mypath\myfolder\!$Unit!.txt') do set numLines=%%a
This command allows you "to skip the first three lines entirely" and process the rest:
for /F "skip=3 delims=" %%a in (C:\Users\c1921\mypath\myfolder\!$Unit!.txt) do echo Processing: "%%a"
However, in my opinion this problem could be entirely avoided if the three first lines in the text file are supressed from the very beginning. I think this file is generated via a VBScript of JScript program that is executed this way:
cscript progname.vbs > C:\Users\c1921\mypath\myfolder\!$Unit!.txt
The first three lines in the text file may be avoided adding //nologo switch this way:
cscript //nologo progname.vbs > C:\Users\c1921\mypath\myfolder\!$Unit!.txt
#ECHO OFF
SETLOCAL
SET /a count=3
SET "first="
FOR /f "skip=3delims=" %%a IN (q25089468.txt) DO (
IF DEFINED first (CALL :show %%a) ELSE (SET "first=%%a")
)
ECHO count=%count%
GOTO :EOF
:show
ECHO first=%first% second=%1
SET /a count+=2
SET "first="
GOTO :eof
I used a file named q25089468.txt containing your data for my testing.
You appear to be asking two entirely different things - how to count the lines and how to skip the first 3, then deliver each succeeding pair to another process.

how to change variable value inside loop in batch

I use the below code in order to create a directory from the value of the first 4 chars of collector text file
#echo off & setlocal enabledelayedexpansion
:loop
set /P txt_file=<Collector.txt
Set collector_id=!txt_file:~0,4!
:: check for existence of [OutputFolder]
:: if [OutputFolder] doesn't exist, create it
if not exist %collector_id% (
echo folder %collector_id% not found
echo creating folder %collector_id%
md %collector_id%
)
xcopy *.txt %collector_id% /v
Del *.txt
goto loop
I want to execute the above loop continuously in order to check if current directory is empty or not. If not I want to make a dir, if does not exist, with name the first 4 chars of collector.txt.
If the directory is not empty everything is ok. When the above is looping and I add collector.txt to the current directory the collector_id does not change.
Where am I wrong?
Is there any other way, expect infinite, loop to do this?
Put setlocal EnableDelayedExpansion at the start, and use !var! instead of %var%. Then it is evaluated every time.