Window batch commands to detect if downloaded file exists? - windows

I use a windows batch file that scans download folder and if it detects label.pdf it sends to local printer. This works fine most of the time but often it detects file before the file completely downloads which causes PDFtoPrinter error. Is there a way to make sure the download process is complete before attempting to detect?
#echo off
cls
:start
IF EXIST "C:\Users\Downloads\label.pdf" (
echo "Found!"
ping 127.0.0.1 -n 1 -w 3000> nul
"C:\Users\Downloads\PDFtoPrinter" label.pdf "4BARCODE 4B-2054A"
ping 127.0.0.1 -n 1 -w 10000> nul
del "C:\Users\Downloads\label.pdf"
) ELSE (
echo "it isn't here!"
)
goto start

You can use the mechanism to check if a file is locked for exclusive access by another application.
#echo off
cls
:start
IF EXIST "C:\Users\Downloads\label.pdf" (
REM check if file is locked
2>nul (>>"C:\Users\Downloads\label.pdf" (call )) && ("C:\Users\Downloads\PDFtoPrinter" label.pdf "4BARCODE 4B-2054A") || (echo file is locked)
) ELSE (
echo "it isn't here!"
)
Timeout /T 10
goto start

Related

Check if file is locked inside a batch file for loop

I have a script that runs through some files and copies them to another location. But the script needs to wait until the file is no longer being written to.
I tried all the solutions here:
How to check in command-line if a given file or directory is locked (used by any process)?
Process a file after a file is finished being written Windows Command Line .bat
BATCH - wait for file to be complete before picking up
But the problem is that they don't work when wrapped in a loop. It always says the file is locked. If the script it cancelled and re-run it correctly finds the file unlocked.
Am I doing something wrong or is there a trick to make this work?
For locking a test file, checkfile.txt, I do:
(
>&2 pause
) >> checkfile.txt
Then the example script to check the file is this:
#echo off
for %%i in (*.txt) do (
:loop
ping localhost -n 5 > nul
echo "check if locked"
powershell -Command "$FileStream = [System.IO.File]::Open('%%i', 'Open', 'Write'); $FileStream.Close(); $FileStream.Dispose()" >NUL 2>NUL || (goto :loop)
echo "NOT locked anymore"
)
You cannot goto in a loop as it will simply break the for loop entirely. Additionally, the exit code or errorlevel is set for the last successful command. In this case being the powershell dispose command. Simply do the loop outside of the code block:
#echo off & setlocal
for %%i in (*.txt) do call :loop %%~i
goto :EOF
:loop
powershell -Command "[System.IO.File]::Open('%1', 'Open', 'Write')">nul 2>&1 && echo %1 not locked || (
echo %1 Locked
("%systemroot%\system32\timeout.exe" /t 3)>nul
goto :loop
)
Note, the conditional operators (and &&) and (or ||) helps to evaluate the exit code without needing to do if and else statements.

Check for a File Periodically in a MS DOS Batch File

I'm writing an MS DOS batch file that looks for a specific file until it is found.
My code gives me the following error after the SET commands
The syntax of the command is incorrect
C:\> If not exist d:\fdev\data\filename.csv
Here's the code:
SET driveltr=d:\
SET envdir=fdev\
SET datadir=data\
SET archivedir=archive\
SET inputdir=c:\Epic\v8.2\Analytics Tools\Epic BI\Input
SET filename=filename.csv
:while1
if not exist %driveltr%%envdir%%datadir%%filename%
(
echo "Waiting to check for file"
ping -n 11 127.0.0.1 > nul
goto :while1
)
You need "" If your path contains spaces. wait till file exists is working this way:
:while
IF EXIST proceed.txt goto :break
echo "Waiting to check for file"
ping -n 11 127.0.0.1 > nul
goto :while
:break

BATCH- How to put a variable into the move command?

Okay, this is my first question on Stackoverflow, so I'll try to make it a good one.
I've searched all over the web and I couldn't find any information to this. I have created a little batch file that prompts you to put in the name of a file that you would like to move. After that, it asks your your usersname. The problem I'm having is cmd tells me I have incorrect syntax.
Can anyone see what I did wrong?
Below is the code I am using. I just pasted in the part that is having trouble.
Thanks guys!
echo Place the file you wish to move to the Windows Startup Folder on your desktop.
echo When you have placed it there, type in the name of your file, NOT INCLUDING the extension.
echo Example: The file's name is: myfile.bat You type in: myfile
set/p "filename=>"
echo %filename%
echo Next, type in your username.
echo Example: acly6
set/p "USERNAME=>"
echo %USERNAME%
ping 192.2.0.0 -n 1 -w 500 > nul
goto MOVE
:MOVE
echo Moving your file to your startup folder.
move C:\Users\%USERNAME%\Desktop\%filename%.bat
C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
ping 192.2.0.0 -n 1 -w 1000 > nul
echo Checking Volumes...
ping 192.2.0.0 -n 1 -w 3000 > nul
if EXIST C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\%filename%goto COMPLETED
goto FAILED
I editted a bit your script:
Surrounded filepaths with double quotes
Added /y parameter to move command to override automatically the file in new location (if exists)
Spotted some issues:
goto MOVE
:MOVE has no sense as it will continue anyway that path.
goto FAILED GOTO COMPLETED - there're no such labels in your script.
Please shout if you have other problems.
#echo off
echo Place the file you wish to move to the Windows Startup Folder on your desktop.
echo When you have placed it there, type in the name of your file, NOT INCLUDING the extension.
echo Example: The file's name is: myfile.bat You type in: myfile
set/p "filename=>"
echo %filename% echo Next, type in your username.
echo Example: acly6
set/p "USERNAME=>"
echo %USERNAME%
ping 192.2.0.0 -n 1 -w 500 > nul
goto MOVE
:MOVE
echo Moving your file to your startup folder.
move /Y "C:\Users\%USERNAME%\Desktop\%filename%.bat" "C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\"
ping 192.2.0.0 -n 1 -w 1000 > nul
echo Checking Volumes...
ping 192.2.0.0 -n 1 -w 3000 > nul
if EXIST "C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\%filename%" goto COMPLETED
goto FAILED
:FAILED

Need help modifying script to use individual files, instead of all files at once

I was wondering if anyone could help me with a very simple rework of this script I inherited. I have no previous experience with batch files and needed to modify this already working script in a very simple manner.
Currently, this script does the following:
- Monitors a folder and looks to see if there are files in it
- If there are, it executes a FTP transfer via command line
- Then, it moves the files into a archive folder created and named with the current timestamp and writes something to a text log file
- If there are no files, the script exits and does nothing.
As of now, the script is looking for, processing, and moving all the files at once. I was looking to see if I could be pointed int the right direction with help on how to modify the script so that it does each file one by one, instead of using . everywhere. Ultimately, I think all I need to do is figure out how to do the loop correctly and read/store the filenames to use as variables instead of using . Any help would be appreciated.
#ECHO OFF
:: Set count of files = 0
SET X=0
:: Set timestamp for processed folders
set TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%.%TIME:~9,2%
:: If more than 0 files exist begin ftp and file archival otherwise exit
FOR %%i IN (c:\Encoded_HL7_Vanderbilt\*.*) DO IF EXIST %%i (SET X=1)
IF [%X%] gtr [0] (cd\..\..
cd\"Program Files (x86)\Ipswitch\WS_FTP 12"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error switching to ftp program directory>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)
wsftppro -s local:C:\Encoded_HL7_Vanderbilt\*.* -d Vandy!Vanderbilt:/incoming/
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error transmitting file to ftp server>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)
md "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error creating archive directory>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)
move "C:\Encoded_HL7_Vanderbilt\*.*" "E:\Processed_HL7_Vanderbilt%1\%TIMESTAMP%"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error moving files to archive directory>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)) ELSE (exit)
echo %TIMESTAMP% File transfer completed successfully>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.success.txt
exit
Give this a walk around the park: if any file generates an error then it will stop processing further files.
#ECHO OFF
set "folder=%~1"
:: Set timestamp for processed folders
set TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%.%TIME:~9,2%
:: If more than 0 files exist begin ftp and file archival otherwise exit
FOR %%a IN (c:\Encoded_HL7_Vanderbilt\*.*) DO (
cd\"Program Files (x86)\Ipswitch\WS_FTP 12"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error switching to ftp program directory>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
wsftppro -s local:%%a -d Vandy!Vanderbilt:/incoming/
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error transmitting "%%a" file to ftp server>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
md "E:\Processed_HL7_Vanderbilt\%folder%\%TIMESTAMP%" 2>nul
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error creating archive directory>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
move "%%a" "E:\Processed_HL7_Vanderbilt\%folder%\%TIMESTAMP%"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error moving "%%a" file to archive directory>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
)
echo %TIMESTAMP% File transfers completed successfully or no files were found>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.success.txt
exit
:done
goto :EOF
try this, it might work for you:
#ECHO OFF &SETLOCAL
:: Set count of files = 0
SET /a count=0
:: Set timestamp for processed folders
set "TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%.%TIME:~9,2%"
cd "%ProgramFiles(x86)%\Ipswitch\WS_FTP 12" || (
echo %TIMESTAMP% Error switching to ftp program directory>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
md "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%" || (
echo %TIMESTAMP% Error creating archive directory>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
:: If more than 0 files exist begin ftp and file archival otherwise exit
FOR %%i IN (c:\Encoded_HL7_Vanderbilt\*) DO (
set /a count+=1
REM I don't know the wsftppro command line parameters, pls. check the man page
wsftppro -s local:"%%~i" -d Vandy!Vanderbilt:/incoming/ || (
echo %TIMESTAMP% Error transmitting file to ftp server>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
move "%%~i" "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%" || (
echo %TIMESTAMP% Error moving files to archive directory>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
)
if %count% equ 0 (
rd "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%" 2>nul
exit /b 1
)
echo %TIMESTAMP% File transfer completed successfully>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.success.txt"

Bat file and labels

I am trying to write a bat file for a network policy that will install a program if it doesn't exist as well as several other functions. I am using GOTO statements depending on whether or not certain criterion are met. However, it seems that the labels are not firing correctly as all of them do.
I have simplified my script so as to grasp some idea of what may be happening.
#echo off
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO :MISSING
:EXISTING
echo file exists
:MISSING
echo file missing
ping localhost -n 5 >NUL
Basically it checks to see that the file "test.txt" exists in folder "c:\test" which id does. So it should echo file exists to the console. However, both "file exists" and "file missing" are echoed to the console. I find that if I remove the file from the folder or simply rename it, it only echoes "file missing"
Why is it running running both labels?
Because a GOTO is just a jump in execution to a point in the script, then execution continues sequentially from that point. If you want it to stop after running 'EXISTING', then you need to do something like this. Note the extra GOTO and new label:
#ECHO OFF
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO :MISSING
:EXISTING
echo file exists
goto :NEXTBIT
:MISSING
echo file missing
:NEXTBIT
ping localhost -n 5 >NUL
It's worth noting though that with cmd.exe (i.e., the NT-based command shells [NT, Win2k, XP, etc]), you can do IF...ELSE blocks like this:
#ECHO OFF
IF EXIST c:\test\test.txt (
ECHO File exists
) ELSE (
ECHO File missing
)
ping localhost -n 5 >nul
...so you can eliminate your GOTOs entirely.
It's because you need to skip over the "missing" bit if it exists:
#echo off
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO :MISSING
:EXISTING
echo file exists
goto :COMMON
:MISSING
echo file missing
:COMMON
ping localhost -n 5 >NUL
You may also want to keep in mind that the current cmd.exe batch language is a fair bit more powerful than that which came with MS-DOS. I would prefer this one:
#echo off
if exist c:\test\test.txt (
echo file exists
) else (
echo file missing
)
ping localhost -n 5 >nul
After you echo file exists the next command is
echo file missing
You need to do something to skip the missing case. Perhaps another goto to a :PING label?
When you're debugging it helps to keep the echo on.
Because GOTO statement moves the execution to that label. To use it in the situation like yours, you need to add another GOTO label.
#echo off
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO MISSING
:EXISTING
echo file exists
GOTO END
:MISSING
echo file missing
GOTO END
:END
ping localhost -n 5 >NUL
#echo off
IF EXIST "c:\test\test.txt" ( :: warning double quotes
GOTO EXISTING
) ELSE ( :: this format best in batch
GOTO MISSING
) :: don't forget
:EXISTING
echo file exists
goto OTHER :: if file exist jump OTHER
:MISSING
echo file missing
:: label is not required
:OTHER
timeout /t 5 >nul
pause

Resources