Pass current file name from loop to label in batch script - batch-file

In a batch script I'm running sqlcmd in a loop that goes through a folder of SQL scripts. I would like to be able to pass the script/output file currently being worked on to a label exterior to the loop in the case of an error.
Here's sample code:
#echo off
#setlocal enabledelayedexpansion
SET _INSTANCE=someinstance
SET _DATABASE=somedatabase
SET "_SCRIPTFOLDER=D:\Scripts for Testing"
SET "_OUTPUTFOLDER=D:\Output for Testing"
FOR %%S IN (
"%_SCRIPTFOLDER%\*.sql"
) DO (
SET /P _MSGa=Generating CSV: %%~nS.csv ... <NUL
sqlcmd -b -S %_INSTANCE% -d %_DATABASE% -i "%%~fS" -s "|" -o "%_OUTPUTFOLDER%\%%~nS.csv" -W
IF ERRORLEVEL >= 1 GOTO sqlcomderrorhandling
SET /P _MSGb=file created. Removing header dashes ... <NUL
REM REM Remove the line with dashes below the header
#FINDSTR /r /b /v /c:"-*|" "%_OUTPUTFOLDER%\%%~nS.csv" > "%_OUTPUTFOLDER%"\tmp.txt
IF ERRORLEVEL >= 1 GOTO findstrerrorhandling
XCOPY /Y "%_OUTPUTFOLDER%"\tmp.txt "%_OUTPUTFOLDER%\%%~nS.csv" >NUL
IF ERRORLEVEL >= 1 GOTO copyerrorhandling
ECHO done.
)
DEL /Q /F "%_OUTPUTFOLDER%"\tmp.txt
GOTO done
:sqlcomderrorhandling
ECHO An error occurred while processing the file %%~nS.csv
:done
#pause
The last ECHO just outputs %~nS.csv, not the actual name of the CSV file. Do I need to utilize functions in some way to do what I want to do?

Based on part of rojo's first comment and my own, would this sort of structure not make more sense?
#Echo Off
Set "_INSTANCE=someinstance"
Set "_DATABASE=somedatabase"
Set "_SCRIPTFOLDER=D:\Scripts for Testing"
Set "_OUTPUTFOLDER=D:\Output for Testing"
If Not Exist "%_OUTPUTFOLDER%\" (Echo Output folder doesn't exist
Timeout 3 /NoBreak >Nul
GoTo :EOF)
If Not Exist "%_SCRIPTFOLDER%\*.sql" (Echo Source folder doesn't contain any SQL files
Timeout 3 /NoBreak >Nul
GoTo :EOF)
CD /D "%_SCRIPTFOLDER%" 2>Nul || (Echo Source folder, %_SCRIPTFOLDER%, is not available.
Timeout 3 /NoBreak >Nul
GoTo :EOF)
For %%A In (*.sql) Do (
Echo Generating CSV: %%~nA.csv ...
SQLCmd -b -S %_INSTANCE% -d %_DATABASE% -i "%%A" -s "|" -o "%_OUTPUTFOLDER%\%%~nA.csv" -W 2>Nul && (
Echo File created. Removing header dashes ...
Findstr "[^-|]" "%_OUTPUTFOLDER%\%%~nA.csv">"%_OUTPUTFOLDER%"\%%~nA.tmp" && (
Move /Y "%_OUTPUTFOLDER%"\%%~nA.tmp" "%_OUTPUTFOLDER%\%%~nA.csv">Nul 2>&1 || (
Echo A Move error occurred while moving %%~nA.tmp
Timeout 2 /NoBreak >Nul)) || (Echo A FindStr error occurred while removing header dashes
Timeout 2 /NoBreak >Nul)) || (Echo A SQLCmd error occurred while processing the file %%~nS.csv
Timeout 2 /NoBreak >Nul))
Pause

Related

I need the script to work on all dav files

Script should run in recursive mode, find DAV files and start DAV to JPG conversions using FFMPEG. The script is working, identifying files in folders and starting conversions when DAV files exist, but is ignoring some DAV files.
When I put these DAV files back in the folder it converts correctly.
What could be wrong?
I thought it might be the speed of the process, since the files are being generated in the folder, the script must wait for the file to be closed and complete to act. I tried to delay the conversion process by 15 seconds using a PING, but it still skips some files.
cd E:\VM01\1002
MD "E:\COLETA SNAPSHOT\SNAPSHOT 1002"
MD "E:\COLETA SNAPSHOT\PROCESSED 1002"
:LOOP01
PING 1.1.1.1 -n 10 -w 6000 >NUL
For /R %%G in (*.Dav) do IF NOT EXIST "%%G" GOTO SKIP01
:LOOP02
PING 1.1.1.1 -n 10 -w 6000 >NUL
For /R %%G in (*.Dav) do IF EXIST "%%G" GOTO SKIP02
REM ALL THIS WILL BE DONE IF THE DAV FILE EXISTS
:
:
:SKIP01
REM 6 SECONDS OF DELAY ...
PING 1.1.1.1 -n 10 -w 6000 >NUL
GOTO LOOP01
:
:
:SKIP02
REM START CONVERSION
PING 1.1.1.1 -n 10 -w 15000 >NUL
For /R %%G in (*.Dav) do IF EXIST "%%G" ffmpeg -i "%%G" -r 0.2 -bt 20M -s 480x300 "%%~nG"%%06d.jpg
for /r %%G in (*.Dav) do Move "%%G" "E:\COLETA SNAPSHOT\PROCESSED 1002"
Move "*.jpg" "E:\COLETA SNAPSHOT\SNAPSHOT 1002"
PING 1.1.1.1 -n 10 -w 3000 >NUL
)
GOTO LOOP01
I have rewritten your script to work in the manner I think your posted example is supposed to, and subject to you running it on windows-vista or newer:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "DavTree=E:\VM01\1002"
Set "DavDone=E:\COLETA SNAPSHOT\PROCESSED 1002"
Set "JpgDone=E:\COLETA SNAPSHOT\SNAPSHOT 1002"
CD /D "%DavTree%" || "%__AppDir__%timeout.exe" /T 3 1>NUL & GoTo :EOF
If Not Exist "%DavDone%\" MD "%DavDone%" || "%__AppDir__%timeout.exe" /T 3 1>NUL & GoTo :EOF
If Not Exist "%JpgDone%\" MD "%JpgDone%" || "%__AppDir__%timeout.exe" /T 3 1>NUL & GoTo :EOF
:ProcessDavs
"%__AppDir__%where.exe" /Q /R . *.Dav
If ErrorLevel 1 "%__AppDir__%timeout.exe" /T 6 1>NUL & GoTo ProcessDavs
For /F "Delims=" %%# In ('Dir /B /S /A:-D-S-L /O:D /T:W *.Dav') Do (
"%__AppDir__%timeout.exe" /T 3 1>NUL
"F:\ull\PathTo\FFmpeg.exe" -i "%%#" -r 0.2 -bt 20M -s 480x300 "%%~n#%%06d.jpg"
If Not ErrorLevel 1 (Move /Y "%%#" "%DavDone%" 1>NUL
Move /Y "%%~n#%%06d.jpg" "%JpgDone%" 1>NUL))
GoTo ProcessDavs
Please note on line 15, I have used "F:\ull\PathTo\FFmpeg.exe", please adjust this to the correct location. If located in %PATH% or E:\VM01\1002, you can edit it to just FFmpeg.exe, if your %PATHEXT% variable is unmodified, you can also remove the .exe, (I'm not recommending either). The issue I highlighted in the comments, does not form part of this answer, however, I have arranged the command to recurse the directories so that it picks up the least recently written .dav file first. This may give additional time for any files still being written to complete before you process them. You can also adjust the 6 second timeout on line 12 and 3 second timeout on line 14 as necessary, if the issue persists.

Send files to a ftp server and then check if it was really sent using .bat

I was making a .bat code to send .txt files to a specific folder on my ftp server. But I also wanted a way to check if these files were really uploaded. I searched a lot on the internet and unfortunately, I realized that it can't be done using .bat command.
So I tried using another way: The .bat will send the files and then will take it back to the folder, if the file already exists in the folder it will show a message that the file was successfully uploaded.
I did this script below, but the part of the "checking if was uploaded" is not working right.
Someone can help me?
#echo off
#setlocal enableextensions
#cd /d "%~dp0"
mode 34,12
color 0a
Ping www.google.nl -n 1 -w 1000 >nul 2>nul
if errorlevel 1 (set internet=Nao foi possivel se conectar ao servidor) else (set internet=Conectado) >nul 2>nul
echo %internet%
if "%internet%"=="No connection" goto 1
if "%internet%"=="Conected" goto 2
:1
echo No connection
echo.
echo Try later...
echo.
pause
exit
:2
( echo open ftp.xxxxxxxxxxx.com
echo xxxxxxx
echo xxxxxxx
echo ascii
echo lcd "c:\Vendas Pay&Go\files"
echo cd "Vendas Cartões Pay&Go"
echo cd "ECO"
echo mput *.txt
echo bye
)> %temp%\ftpsend.dat
ftp -i -s:%temp%/ftpsend.dat >nul 2>nul
del /f /s /q %temp%\ftpsend.dat >nul 2>nul
( echo open ftp.xxxxxxx.com
echo xxxxxxx
echo xxxxxxx
echo ascii
echo lcd "c:\Vendas Pay&Go\files"
echo cd "Vendas Cartões Pay&Go"
echo cd "ECO"
echo mget *.txt
echo bye
)> %temp%\ftpsend.dat
ftp -i -s:%temp%/ftpsend2.dat >nul 2>nul
del /f /s /q %temp%\ftpsend2.dat >nul 2>nul
if %*.txt% exist goto3
:4
echo File was not uploaded
pause
:3
echo File Uploaded.
del /s /f /q "c:\Vendas Pay&Go\files\*.txt"
If you want to conditional execution to display a message you can do something like this. The && means the previous command was successful. The || means the previous command was not successful.
(ftp -i -s:%temp%/ftpsend.dat | find /I "file successfully transferred" >nul) && (echo File Successfully Transferred) || ( echo File not transferred. Tray again later.)
Updated version based on comment below
(ftp -i -s:%temp%/ftpsend.dat | find /I "file successfully transferred" >nul) && (
echo File successfully sent.
del /f /s /q "c:\Vendas Pay&Go\files\*.txt" >nul
) || (
cls
echo File not uploaded. Try later.
)

unrar a password protected archive in batch

I want to use a batch file to automatically extract files from a password protected rar archive.
I tried this code:
#echo off
UNRAR E -INUL -P ne2020 "%~dp0program.rar"
pause
but the output that the cmd window that showed to me tells me that unrar aren't an internal/external command.
how to fix that?
You can give a try with this batch file :
#echo off
Title Unzip Winrar Files in command line
color 0A
Mode con cols=75 lines=10
Set "file=%~dp0program.rar"
set "RAR_Password=ne2020"
Set Log=%~n0_UnzipLog.txt
for %%i in ("%file%") do ( set "DEST=%~dp0%%~ni" )
set strProgramFiles=%ProgramFiles%
if exist "%ProgramFiles(x86)%" set strProgramFiles=%ProgramFiles(x86)%
Set Unrar="%strProgramFiles%\WinRAR\UnRar.exe"
If not exist "%DEST%" MD "%DEST%"
If Exist %Unrar% ( Goto :Unrar ) else ( Goto :Fail )
:Unrar
%UNRAR% E -inul -y -p%RAR_Password% "%file%" "%DEST%">nul 2>&1
IF "%ERRORLEVEL%" EQU "0" ( GOTO Succes ) Else ( Goto Fail )
:Succes
Echo(
Echo All Files are unzipped succesfuly ! in "%DEST%"
Echo All Files are unzipped succesfuly ! in "%DEST%" > "%Log%"
Start "" /MAX "%Log%"
Timeout /T 3 /nobreak>nul
Exit /b
:Fail
Color 0C
Echo(
echo There was an error !
echo There was an error ! > "%Log%"
Start /MAX "" "%Log%
Timeout /T 3 /nobreak>nul
after I checked the comments I found the answers.
there is 2 ways.
1st:
putting unrar.exe file in the same directory with the batch file
2nd:
adding this line:
cd C:\Program Files\WinRAR\
without forgetting to not to separate between -p and the password.

Batch Script ErrorLevel Output

I need help - I am trying to output any ErrorLevel that is 1 or greater into a log file. When I issue the command the log file never get's generated. Any help would be greatly appreciated.
Script:
for /f "delims=" %%i in (C:\_\Restart\Computer.txt) do (
start "%%i" \_\PStools\psexec \\%%i -u Administrator -p Password -i c:\restart.cmd
if not %errorlevel%==0 echo %errorlevel% > error.log
)
This script allows me to use PSEXEC and issue a restart command to all the computer at once. However several of them fail and I'd like to know which ones fail.
Thanks!
Is this the format I should use?
setlocal EnableDelayedExpansion
for /f "delims=" %%i in (C:\_\Restart\Computer.txt) do (
start "%%i" \_\PStools\psexec \\%%i -u Administrator -p Password -i c:\restart.cmd
if errorlevel 1 echo !errorlevel! > error.log
)
Script V3:
setlocal EnableDelayedExpansion
for /f "delims=" %%i in (C:\temp\list.txt) do (
start "" "shutdown" /m \\%%i -r -f -t 900
echo !errorlevel! && echo %%i
if errorlevel 1 echo !errorlevel! >> c:\temp\log.txt && echo %%i >> c:\temp\log.txt
)
-m = use remote computer
-r = reboot
-f = Force reboot
-t = delay of time before rebooting
you can use shutdown -? for more help on argument that can be passed to the reboot command.
Script v4 without the start command:
setlocal EnableDelayedExpansion
for /f "delims=" %%i in (C:\temp\list.txt) do (
shutdown /m \\%%i -r -f -t 900
echo !errorlevel! && echo %%i
if errorlevel 1 echo !errorlevel! >> c:\temp\log.txt && echo %%i >> c:\temp\log.txt
)

Batch file over network path

I have the following batch script to make life easier at work.
Here is what it is supposed to work:
1- Drag and drop some file onto the .bat
2- Choose file's destination on the "menu"
3- Script copy's files to destination folder
4- Script executes remote procedure (that's the PSexec line)
5- Script copy's the result of the remote procedure to other folders.
And this works fine... except for a "small" detail with which i need some help.
When i try to copy the network location \10.250.39.116\d%... if i haven't previously logged into that machine it wont work.
I've been looking into the 'net use' command to overcome this, but i'm not sure if it suits my needs.
There are a total of 4 different machines i need to authenticate, dependent on the choice of the menu.
Actual Question:
Can i log in to such machines with the batch, and avoid creating duplicate connections every time i run the script ? If so, how?
Thank you for your time!
:)
I know the paths I have all point to the same place :)
#echo off
setlocal enabledelayedexpansion
ECHO.
ECHO ...............................................
ECHO PRESS 1, 2 OR 3 to select your task, or 4 to EXIT.
ECHO ...............................................
ECHO.
ECHO 1 - Compilar em Qualidade
ECHO 2 - Compilar na HSDEV
ECHO 3 - Compilar nas DEMOS
ECHO 4 - EXIT
ECHO.
SET /P M=Type 1, 2, 3, or 4 then press ENTER:
IF %M%==1 GOTO :QUAL
IF %M%==2 GOTO :HSDEV
IF %M%==3 GOTO :DEMO
IF %M%==4 GOTO EOF
:QUAL
set "PathForms6=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\compilador\fmb6i\GH\"
set "PathForms10=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\compilador\fmb10\GH\"
set PathCompilador=\\10.250.39.116 -u Administrator -p Password1 cmd "/C d: & cd d:\GLINTTHSIAS\GLINTTHS\compilador & GH_PRIV_10_02_Forms.bat"
set PathDestinoPriv=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\PRIV\GH
set PathDestinoPub=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\PUB\GH
goto :PROCESSA
goto EOF
:HSDEV
set "PathForms6=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\compilador\fmb6i\GH\"
set "PathForms10=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\compilador\fmb10\GH\"
set PathCompilador=\\10.250.39.116 -u Administrator -p Password1 cmd "/C d: & cd d:\GLINTTHSIAS\GLINTTHS\compilador & GH_PRIV_10_02_Forms.bat"
set PathDestinoPriv=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\PRIV\GH
set PathDestinoPub=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\PUB\GH
goto :PROCESSA
goto EOF
:DEMO
set "PathForms6=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\compilador\fmb6i\GH\"
set "PathForms10=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\compilador\fmb10\GH\"
set PathCompilador=\\10.250.39.116 -u Administrator -p Password1 cmd "/C d: & cd d:\GLINTTHSIAS\GLINTTHS\compilador & GH_PRIV_10_02_Forms.bat"
set PathDestinoPriv=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\PRIV\GH
set PathDestinoPub=\\10.250.39.116\d$\GLINTTHSIAS\GLINTTHS\PUB\GH
goto :PROCESSA
goto EOF
:PROCESSA
set argCount=0
for %%x in (%*) do (
set /A argCount+=1
set "argVec[!argCount!]=%%~nx"
set "pathVec[!argCount!]=%%~dpx"
)
rem echo Number of processed arguments: %argCount%
for /L %%i in (1,1,%argCount%) do (
echo Vou compilar %%i - "!argVec[%%i]!"
if exist %PathForms6%!argVec[%%i]!.* del /q %PathForms6%!argVec[%%i]!.*
if exist %PathForms10%!argVec[%%i]!.* del /q %PathForms10%!argVec[%%i]!.*
robocopy "!pathVec[%%i]!." %PathForms6% !argVec[%%i]!.fmb > nul
)
c:
cd c:\pstools
psexec %PathCompilador%
for /L %%i in (1,1,%argCount%) do (
if exist "%PathForms10%!argVec[%%i]!.fmx" (
xcopy %PathForms10%!argVec[%%i]!.fmx %PathDestinoPriv% /y
xcopy %PathForms10%!argVec[%%i]!.fmx %PathDestinoPub% /y)
)
pause
How much testing have you done with net use? Try running it twice at the command line. Notice how the output changes at the second running:
As you can see, where a connection has already been established, net use will output a summary of the connection rather than creating a duplicate connection.
If you prefer, you could use conditional execution or errorlevel checking. Using this method, you can avoid calling net use until xcopy fails, which should only be the first time. Here's a short example, simply to illustrate the mechanics:
#echo off
setlocal
ping -n 1 10.250.39.116 | find /i "TTL=" >NUL || (
echo 10.250.39.116 is offline. Unable to continue. Press any key to exit.
pause >NUL
goto :EOF
)
call :xcopy "%~1" "destination"
echo Press any key to exit.
pause >NUL
net use \\10.250.39.116\d$ /delete >NUL 2>NUL
goto :EOF
:xcopy <source> <dest_dir>
xcopy /L "%~1" "%~2" 2>NUL || (
net use \\10.250.39.116\d$ /user:username password >NUL 2>NUL
xcopy /L "%~1" "%~2"
)
goto :EOF

Resources