I'd like to write a batch file that logs data. Each time it runs, it should log data in a new, sequentially numbered directory.
If I were doing this in BASH I would simply do:
~/$ for i in {1..25}; do if [[ ! -d log-$i ]]; then mkdir log-$i; break; fi; done; echo "log-$i"
log-1
~/$ for i in {1..25}; do if [[ ! -d log-$i ]]; then mkdir log-$i; break; fi; done; echo "log-$i"
log-2
~/$ for i in {1..25}; do if [[ ! -d log-$i ]]; then mkdir log-$i; break; fi; done; echo "log-$i"
log-3
What would be the equivalent of this in Windows (XP or more recent) batch programming?
[EDIT]
This is what I implemented, and it doesn't do what I'd hoped:
set "UNIT_ID=00534"
echo Check Thermo-Cal
IF NOT EXIST "C:\Thermo-Cal\NUL" "md C:\Thermo-Cal"
echo Check Thermo-cal\%UNIT_ID%
IF NOT EXIST "C:\Thermo-Cal\%UNIT_ID%\NUL" "md C:\Thermo-Cal\%UNIT_ID%"
FOR /L %%F IN (1,1,99) DO (
IF NOT EXIST "C:\Thermo-Cal\%UNIT_ID%\log-%%F\NUL" (
"md C:\Thermo-Cal\%UNIT_ID%\log-%%F"
set "LOG_DIR=C:\Thermo-Cal\%UNIT_ID%\log-%%F"
goto dir_set
)
)
echo "Couldn't create a directory to save stuff."
goto :EOF
:dir_set
echo "Stuff will get saved in: %LOG_DIR%"
Running on Windows 7 (cmd) gives:
c:\batch\log-dir.bat
Check Thermo-Cal
The filename, directory name, or volume label syntax is incorrect.
Check Thermo-Cal\00534
The filename, directory name, or volume label syntax is incorrect.
The filename, directory name, or volume label syntax is incorrect.
"Stuff will get saved in: C:\Thermo-Cal\00534\log-1"
The first time the batch file runs, the log-1 is created.
Running the command a second time produces the exact same results, I would hope it create log-2.
Turning off the #echo off shows that the loop never breaks out early and runs (in this case) 99 times.
FOR /L %%F IN (1,1,25) DO (
IF "condition" "md C:\some\folder\log-%%F"
ECHO log-%%F
PAUSE
)
Inserted pause so you can see each output before it moves onto the next sequential number. Remove PAUSE when you finalize your script.
EDIT: Adding an IF NOT EXIST condition
FOR /L %%F IN (1,1,25) DO (
IF NOT EXIST "C:\some\folder\log-%%F\NUL" "md C:\some\folder\log-%%F"
ECHO log-%%F
PAUSE
)
When using IF [NOT] EXIST statements on directories, you must specify .\NUL as a file, as Windows normally only passes the condition on files and not folders. And in Windows, the NUL file ALWAYS exists in an existing directory.
EDIT2: Making log-%%F accessible outside of the loop
FOR /L %%F IN (1,1,25) DO (
IF NOT EXIST "C:\some\folder\log-%%F\NUL" ("md C:\some\folder\log-%%F" && SET dir%%F=C:\some\folder\log-%%F)
)
ECHO %dir1%
ECHO %dir2%
ECHO %dir3%
Plug that into a batch file and try it.
This worked on Windows 7:
set "UNIT_ID=00534"
echo Check Thermo-Cal
IF NOT EXIST C:\Thermo-Cal\NUL md C:\Thermo-Cal
echo Check Thermo-cal\%UNIT_ID%
IF NOT EXIST C:\Thermo-Cal\%UNIT_ID%\NUL md C:\Thermo-Cal\%UNIT_ID%
FOR /L %%F IN (1,1,99) DO (
IF NOT EXIST C:\Thermo-Cal\%UNIT_ID%\log-%%F\NUL (
md C:\Thermo-Cal\%UNIT_ID%\log-%%F
set "LOG_DIR=C:\Thermo-Cal\%UNIT_ID%\log-%%F"
goto dir_set
)
)
echo "Couldn't create a directory to save stuff."
goto :EOF
:dir_set
echo "Stuff will get saved in: %LOG_DIR%"
You have to be careful where you use quotes, as in batch scripting, quoted content can be seen as literal strings instead of code.
set "UNIT_ID=00534"
echo Check Thermo-Cal
IF NOT EXIST "C:\Thermo-Cal\NUL" (md C:\Thermo-Cal)
echo Check Thermo-cal\%UNIT_ID%
IF NOT EXIST "C:\Thermo-Cal\%UNIT_ID%\NUL" (md C:\Thermo-Cal\%UNIT_ID%)
FOR /L %%F IN (1,1,99) DO (
IF NOT EXIST "C:\Thermo-Cal\%UNIT_ID%\log-%%F\NUL" (
md C:\Thermo-Cal\%UNIT_ID%\log-%%F
set LOG_DIR=C:\Thermo-Cal\%UNIT_ID%\log-%%F
goto dir_set
)
)
echo "Couldn't create a directory to save stuff."
goto :EOF
:dir_set
echo Stuff will get saved in: %LOG_DIR%
Related
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
The batch here inserts file correctly but provides odd output for the IF EXIST. I have verified the issue as being with the statement by the echos before and after it, but the IF EXIST is pinging as true if the copy is going off. The error I get is the console text of "The system can not find the drive specified."
Code is below.
ECHO OFF
ECHO This batch file will place the background and user icons for Windows 7 install.
SET directoryName=C:\Users\yourname\Desktop\BatchTestingFolder\ImageInsertReal\testfolder
ECHO %directoryName%
PAUSE
IF EXIST guest.bmp (
::If image exists
ECHO 1
::1--
IF EXIST %directoryName% (
::If directory exists
::insert all below images
::2--
ECHO 2
COPY /-Y guest.bmp %directoryName% ) ELSE (
::Else echo directory doesnt exist
::2--
ECHO The folder %directoryName% does not exist.
goto ENDER ) ) ELSE (
::Else echo image doesn't exist
::1--
ECHO Images do not exist in current batch file directory.
goto ENDER )
::Exit insertion
:ENDER
PAUSE
I would highly advise you use a syntax of coding that is readable.
Proper indentation helps with readability of parentheses code blocks.
Using a double colon as a comment inside a parentheses code block can cause undesirable code output.
You can use a backslash to make sure you are testing for the existence of a directory.
Use quotes around your file names and file paths to protect spaces and special characters.
This may fix your problems.
#ECHO OFF
ECHO This batch file will place the background and user icons for Windows 7 install.
SET "directoryName=C:\Users\yourname\Desktop\BatchTestingFolder\ImageInsertReal\testfolder"
ECHO %directoryName%
PAUSE
IF EXIST guest.bmp (
REM If image exists
ECHO 1
REM 1--
IF EXIST "%directoryName%\" (
REM If directory exists
REM insert all below images
REM 2--
ECHO 2
COPY /-Y guest.bmp "%directoryName%\"
) ELSE (
REM Else echo directory doesnt exist
REM 2--
ECHO The folder %directoryName% does not exist.
goto ENDER
)
) ELSE (
REM Else echo image doesn't exist
REM 1--
ECHO Images do not exist in current batch file directory.
goto ENDER
)
::Exit insertion
:ENDER
PAUSE
I have a batch checking for a specific file like this:
if exist "C:\Program Files\App\App version number\file.exe" (
echo EXISTS
) else (
echo NOT EXIST!
)
I want to be able to check for the file.exe in any version so it might be in:
"C:\Program Files\App\App v.1\file.exe"
"C:\Program Files\App\App v.2\file.exe"
How can I skip the version number as a requirement inside the path?
Here is an example using the WHERE command with conditional operators.
where /Q /R "C:\Program Files\App" file.exe && echo found || echo not found
Might be a bit overkill but should work.
main.bat:
#echo off
for /f "tokens=*" %%i in ('sub.bat') do (
if "x%%i"=="x" (
echo "Not found!"
) ELSE (
echo "Found in %%i"
)
)
sub.bat:
#echo off
set your_path="C:\Your Path\"
cd /d %your_path%
for /r %%p in (file.exe) do echo %%p
Explanation:
The main batch is the one to execute. It reads the output of the sub batch and reacts properly.
Set the root for the search to the variable your_path. It will change the directory and then searches with an /Recursive loop through the current directory and looks for the file you set in the parenthesis. If the file is found, it will echo that to get read by the main file.
Feel free to ask further questions :)
setlocal
set AppDir=
for /d %%d in ("C:\Program Files\App\App v*") do if exist "%%d\file.exe" set "AppDir=%%d"
if defined AppDir (
echo EXISTS - it's in "%AppDir%"
) else (
echo NOT EXIST!
)
endlocal
(Update: Edited to put quotes around variables in case there's a filename that contains a special character such as &. Thanks to #aschipfl for pointing this out. On the other hand, there's no need to use %%~d instead of just %%d because %%d won't have any quotes anyway.)
I always let my photocamera create a RAW-file ànd a JPG when taking photos.
In my work-flow for "developing" the RAW-files, I first go through the JPG's and delete the JPG's from the photos which I don't want to process. I am then left with a directory with all the RAW-files and some of the JPG's:
DSC01864.ARW
DSC01865.ARW
DSC01866.ARW
DSC01867.ARW
DSC01868.ARW
DSC01868.JPG
DSC01869.ARW
DSC01869.JPG
DSC01870.ARW
DSC01870.JPG
I want to delete the RAW files for which I already deleted the JPG's. I have made a Windows batch-script for this, but for some reason it doesn't work; it deletes all the RAW-files :-(
The script:
#echo off
for %%F in (*.arw) do (
rem echo %%~nF.jpg
if exist {%%~nF.jpg} (
echo File %%F is kept
echo ------------------------
) else (
del %%F
echo File %%F is removed
echo ------------------------
) )
goto :EOF
I would like to now what I am doing wrong....
Apparently it doesn't recognise any JPG-file.
BTW, I used to have a working script for Bash (Linux), but I use DXO optics on Windows nowadays and am in need of a Windows-version. My bash-script:
#!/bin/bash
for rawfile in *.ARW
do
jpegfile="`basename "$rawfile" .ARW`.JPG"
if [ ! -e $jpegfile ]
then
/bin/rm -f $rawfile
fi
done
Your mistake is in line
if exist {%%~nF.jpg} (
{ and } have no special meaning and are therefore read as literal characters.
So this IF condition checks for *.jpg files with { at beginning and }at end of the file name.
Simply remove { and } and your batch file works.
I have added the creation of a sub-directory called RAW and the deletion of all the original JPG's from the camera (as I don't use them anymore).
And I've creared a 2nd script which can be run after the "developing part" of the workflow. This 2nd script checks which RAW-files have been processed succesfully and moves those RAW-files and their configuration-file (made by DXO Optics) to the RAW sub-directory. I keep them archived in case I want to process them in the future again.
In the main directory it leaves:
DSC01868_DxO.JPG
DSC01869_DxO.JPG
DSC01870_DxO.JPG
While in the RAW-subdirectory one gets:
DSC01868.ARW
DSC01868.ARW.dop
DSC01869.ARW
DSC01869.ARW.dop
DSC01870.ARW
DSC01870.ARW.dop
First script (Windows batch), which deletes the unwanted RAW's, creates a RAW-directory and deletes all original JPG's:
#echo off
for %%F in (*.arw) do (
if exist %%~nF.jpg (
echo File %%F is kept
echo ------------------------
) else (
del %%F
echo File %%F is removed
echo ------------------------
) )
del *.jpg
mkdir RAW
goto :EOF
The 2nd script (Windows batch), which moves the RAW-files and their configuration files to the RAW-subdirectory:
#echo off
for %%F in (*.arw) do (
if exist %%~nF_DxO.jpg (
move %%F RAW\
move %%F.dop RAW\
echo %%F en %%F.dop are moved
echo ------------------------
) else (
echo Nothing moved
echo ------------------------
) )
goto :EOF
I haven made the Bash (Linux) equivalents of these scripts as well.
The first script:
#!/bin/bash
for rawfile in *.ARW
do
jpegfile="`basename "$rawfile" .ARW`.JPG"
if [ ! -e $jpegfile ]
then
/bin/rm -f $rawfile
fi
done
mkdir RAW
rm *.JPG
The 2nd script:
#!/bin/bash
for rawfile in *.ARW
do
jpegfile="`basename "$rawfile" .ARW`_DxO.jpg"
dopfile="$rawfile.dop"
echo "$jpegfile"
if [ -e $jpegfile ]
then
mv $rawfile ./RAW/$rawfile
mv $dopfile ./RAW/$dopfile
fi
done
I am trying to do the following,
Verify.exe crawls a directory structure and checks files one by one for any defects. File is passed to verify.exe as a command line argument. If any defects are found in a file it prints an error code (one line string). If file is legitimate nothing is printed. I want to create a folder for each error code and copy the faulty file to the folder so I can take a look at it. If file has no errors nothing is done.
Files need to be checked are in D:\Test\docs\r1 - For testing purpose I have only one file in D:\Test\docs\r1.
::#echo off
CD D:\Test\doc\r1\
FOR /R %%a IN (*) DO (
ECHO %%a
FOR /F %%b IN ('D:\Test\doc\Verify.exe /i:"%%a"') do SET MyVAR=%%b
IF NOT "%MyVAR%" == "" (
ECHO "IF one"
IF EXIST D:\Test\doc\%MyVAR% (
ECHO "IF two"
MD D:\Test\doc\%MyVAR%
)
COPY %%a D:\Test\doc\%MyVAR%
)
SET MyVAR=
ECHO "------------------------"
)
I get the following echo on the command line.
D:\Test\doc>CD D:\Test\doc\r1\
D:\Test\doc\r1>FOR /R %a IN (*) DO (
ECHO %a
FOR /F %b IN ('D:\Test\doc\Verify.exe /i:"%a"') do SET MyVAR=%b
IF NOT "" == "" (
ECHO "IF one"
IF EXIST D:\Test\doc\ (
ECHO "IF two"
MD D:\Test\doc\
)
COPY %a D:\Test\doc\
)
SET MyVAR=
ECHO "------------------------"
)
D:\Test\doc\r1>(
ECHO D:\Test\doc\r1\A5 Incident Management.doc
FOR /F %b IN ('D:\Test\doc\Verify.exe /i:"D:\Test\doc\r1\A5 Incident Management.doc"') do SET MyVAR=%b
IF NOT "" == "" (
ECHO "IF one"
IF EXIST D:\Test\doc\ (
ECHO "IF two"
MD D:\Test\doc\
)
COPY D:\Test\doc\r1\A5 Incident Management.doc D:\Test\doc\
)
SET MyVAR=
ECHO "------------------------"
)
D:\Test\doc\r1\A5 Incident Management.doc
D:\Test\doc\r1>SET MyVAR=0x8004170b
"------------------------"
D:\Test\doc\r1>
Could someone help me in following issues..
The loop has run three times
No folders are created
It seems there is an issue in assigning exe command line output to MyVar
Thank you in advance
Assuming the output of your verify.exe command is correct, you probably should enable delayed expansion (at the top of your batch file):
SETLOCAL ENABLEDELAYEDEXPANSION
and use the ! syntax for variable used within a loop (replace %MYVAR% with !MYVAR!)
Otherwise, within the for-loop, %MYVAR% is only evaluated before the first run (where no value is defined).