Unable to display the value of a variable in batch file - windows

I have a batch file to count the number of specific files in a folder. The contents are given below:
set xx = %DATE:~10,4%%DATE:~4,2%%DATE:~7,2%
set count=dir C:\Archive\*%xx%.csv | find "File(s)"
echo %count%
But the output of the last command displays as
echo
ECHO is on
What am I doing wrong here?? Can anyone help please?

To execute a command an retrieve its output you need the for /f command (see for /? help)
set "xx=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%"
for /f %%a in ('dir /a-d /b "c:\Archive\*%xx%.csv" ^| find /c /v ""') do set "count=%%a"
echo %count%
This will execute a dir command for the required files without folders included in the list, in bare format (no header, summary and no aditional file info) and instead of search for the File(s) (in a different windows locale the text is different), it uses find to count (/c) the number of non empty lines (/v ""). The output is a number that is stored in the for replaceable parameter %%a, and then copied to the required variable

Related

How to identify/get the file by its timestamp in a batch file?

I have a list of csv files with date and time appended like "Account_data_yyyymmdd.csv" which are added daily along with its timestamp to source dir .I have to identify latest file ie.'Account_data_2020_08_05.csv' and set the value in variable . so i can pass it as argument
Files in source dir
Account_data_2020_08_05.csv
Account_data_2020_08_04.csv
Account_data_2020_08_03.csv
I have to find the recently placed file based on its timestamp & pass it as input for calling another batch process. Highlighted text is the argument to batch file.How to find latest file based on its timestamp and pass it as argument for
echo "start"
call process.bat "C:\CSVDataLod" AccntDataloadprocess ***"dataAccess.name=C:\SourceDir\ Account_data_%year%_%month%_%date%.csv"***
That's surprisingly easy. Use dir with the /on switch to sort by name (see dir /? for that switch and the others I used, if you are not familiar with them) and put a for /f loop around to capture the output. The following code sets the variable %last% to each line of the output, keeping the last one only:
for /f "delims=" %%a in ('dir /a-d /on /b Account_data_*.csv') do set "last=%%a"
echo %last%
The easiest and fastest method to get name of CSV file with newest date in file name is using command DIR with option /O-N to get the CSV file names output ordered by name in reverse order. The file name with newest name is output first by DIR in this case. The output of DIR has to be captured and processed with FOR. The FOR loop is exited after running the other batch file with first file name output by DIR.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FileFound="
set "FileNamePattern=Account_data_20??_??_??.csv"
if /I "%~x1" == ".csv" set "FileNamePattern=%~nx1"
for /F "delims=" %%I in ('dir "C:\SourceDir\%FileNamePattern%" /A-D /B /O-N 2^>nul') do (
echo Processing file %%I ...
call process.bat "C:\CSVDataLod" AccntDataloadprocess "dataAccess.name=C:\SourceDir\%%I"
if /I not "%~1" == "/A" goto EndBatch
set "FileFound=1"
)
if not defined FileFound echo There is no file "%FileNamePattern%" in directory "C:\SourceDir".
:EndBatch
endlocal
I recommend to open a command prompt and run
dir "C:\SourceDir\Account_data_20??_??_??.csv" /A-D /B /O-N
Then you know which lines are processed by FOR. Next run
dir "C:\SourceDir\Account_data_20??_??_??.csv" /A-D /B
dir "C:\SourceDir\Account_data_20??_??_??.csv" /A-D /B /ON
to see how DIR outputs the CSV file names without specifying a specific order resulting in printing the file names as returned by the file system and explicitly ordered by name in alphabetical order instead of reversed alphabetical order.
The file system NTFS returns a list of file names matched by a wildcard pattern in local specific alphabetic order while FAT file systems like FAT16, FAT32, exFAT return the file names not ordered at all. In real all file systems return the file names in order as stored in the table of the file system. The file systems use just different methods on how to add a file name to table of the file system. The FAT file systems append a new file name always at end of the table of a directory while NTFS inserts a new file name in table of a directory using a local specific alphabetic sort algorithm.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.
Edit:
The batch file can be run with /a or /A as argument to process all CSV files matching the wildcard pattern from newest to oldest instead of just the newest. The batch file can be also run with name of a .csv file in source directory to process this specific CSV file instead of the newest CSV file.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
endlocal /?
for /?
goto /?
setlocal /?

Backup script - find file by pattern, read it's full name and pass to script

I'm trying to use 7-Zip for backup purposes.
I have already wrote script for full backup:
#echo off
set source="c:\Source"
set destination="C:\Dest"
set dd=%DATE:~0,2%
set mm=%DATE:~3,2%
set yyyy=%DATE:~6,4%
set curdate=%dd%-%mm%-%yyyy%
"C:\Program Files\7-Zip\7z.exe" a -tzip -ssw -mx6 -r0 %destination%\Full_%curdate%.zip %source%
The new script intended for incremental backup is started after the full backup is made. But I don't really get how to make my second script to read files from directory and look for the file staring like full_xx_xx_xxxx.zip and assign its filename to a variable and then pass it to the script for incremental backup.
I tried script below, but it's not working:
#echo off
set source="c:\Source"
set destination="c:\Dest"
set exten="Full_*.zip"
set passwd="NAS"
set dd=%DATE:~0,2%
set mm=%DATE:~3,2%
set yyyy=%DATE:~6,4%
set curdate=%dd%-%mm%-%yyyy%
for %%a in %exten do echo %%a
"C:\Program Files\7-Zip\7z.exe" u -tzip -ssw -r0 %destination%\%%a.zip -u- -up0q3x2z0!"%destination%\diff_%date%.zip" %source%
There are multiple mistakes in both scripts.
I recommend reading first How to set environment variables with spaces? and Why is no string output with 'echo %var%' after using 'set var = text' on command line?. The syntax set variable="value in quotes" is often not good because it assigns the string "value in quotes" with the double quotes and all trailing spaces/tabs which might exist also in batch file to the environment variable with name variable. This syntax is problematic on concatenating the string value of the environment variable with other strings as done in posted code with %destination% because of the " being now somewhere in middle of the final argument string instead of enclosing the entire argument string. Better is the syntax set "variable=value without or with spaces" with " left to variable name because of the double quotes are interpreted now as argument string separators and perhaps existing spaces/tabs on line after second " are ignored by Windows command processor.
The usage of dynamic environment variable DATE makes it possible to quickly get current locale date in a format usable for file/folder names. But it must be taken into account that the date format of value of DATE depends on region/country/locale set for the user account which is used on running the batch file. I suppose that echo %DATE% results in an output of a date in format DD.MM.YYYY and so the command lines using DATE are correct for you with your user account according to the configured country.
The FOR command line is completely wrong and results in an exit of batch file execution with an error message output by cmd.exe interpreting the batch file line by line. This error output can be seen on running the batch file from within a command prompt window instead of double clicking on the batch file. See debugging a batch file for details on how to debug a batch file to find syntax errors like this reported by Windows command processor during execution of a batch file.
So I suggest for the first batch file:
#echo off
set "Source=C:\Source"
set "Destination=C:\Dest"
set "CurrentDate=%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%"
"%ProgramFiles%\7-Zip\7z.exe" a -tzip -ssw -mx6 -r0 "%Destination%\Full_%CurrentDate%.zip" "%Source%"
The current locale date is assigned to the environment variable CurrentDate in format YYYY-MM-DD instead of DD-MM-YYYY. The date format YYYY-MM-DD is the international date format according to ISO 8601. It has one big advantage in comparison to all locale date formats in file names: The file names with date in format YYYY-MM-DD sorted alphabetically as usual are at the same time sorted chronological. That makes it much easier for people and scripts finding a specific file in a list of file names with date in file name.
I am not really sure what you want to do with the second batch file. So I can only suppose what you want to do and suggest for the second batch file:
#echo off
set "Source=C:\Source"
set "Destination=C:\Dest"
set "CurrentDate=%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%"
set "NamePattern=Full_*.zip"
for /F "skip=1 eol=| delims=" %%I in ('dir "%Destination%\%NamePattern%" /A-D /B /O-N 2^>nul') do (
"%ProgramFiles%\7-Zip\7z.exe" u -tzip -ssw -r0 "%Destination%\%%I" -u- -up0q3x2z0!"%Destination%\Diff_%CurrentDate%.zip" "%Source%"
goto Done
)
:Done
The FOR loop runs command DIR with using a separate command process started in background to get the list of Full_*.zip file names in destination directory sorted reverse by name which means the full backup ZIP file created today before with first batch file is at top on using date format YYYY-MM-DD and the previously created ZIP file from yesterday (or whenever the last but one full ZIP file was created) is output as second line.
FOR skips the first line with ZIP file name with current date and runs 7-Zip with previously created ZIP file (yesterday) to create the difference ZIP file. Then the FOR loop is exited without processing all other full ZIP files with a jump to the label below the FOR loop.
Both batch files together:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Source=C:\Source"
set "Destination=C:\Dest"
set "CurrentDate=%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%"
set "NamePattern=Full_*.zip"
rem Create full ZIP backup.
"%ProgramFiles%\7-Zip\7z.exe" a -tzip -ssw -mx6 -r0 "%Destination%\Full_%CurrentDate%.zip" "%Source%"
rem Create difference ZIP backup with files added/changed in source directory
rem in comparison to the files compressed into last but on full ZIP backup.
for /F "skip=1 eol=| delims=" %%I in ('dir "%Destination%\%NamePattern%" /A-D /B /O-N 2^>nul') do (
"%ProgramFiles%\7-Zip\7z.exe" u -tzip -ssw -r0 "%Destination%\%%I" -u- -up0q3x2z0!"%Destination%\Diff_%CurrentDate%.zip" "%Source%"
goto Done
)
:Done
endlocal
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
for /?
rem /?
set /?
setlocal /?

Delete files by Specifying directory

I am using the following batch script while deletes files below a certain size.
#echo off
setlocal
:: Size is in bytes
set "min.size=100000"
for /f "usebackq delims=;" %%A in (`dir /b /A:-D *.*`) do If %%~zA LSS %min.size% del "%%A"
This works if I put the batch file inside the folder but it deletes the batch file also.
However how do I keep the batch file at a different position and specify the directory path explicitly?
The easiest solution is making the directory on which to delete files like C:\Temp\Test temporarily the active directory.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Size is in bytes
set "min.size=100000"
set "FullBatchFileName=%~f0"
pushd "C:\Temp\Test"
rem Do nothing if the command line above fails unexpected.
if errorlevel 1 goto EndBatch
for /F "eol=| delims=" %%I in ('dir * /A-D-H /B /OS 2^>nul') do if not "%FullBatchFileName%" == "%%~fI" if %%~zI LSS %min.size% ( del "%%I" ) else goto DeletionDone
:DeletionDone
popd
:EndBatch
endlocal
The DIR command line is executed by FOR in a separate command process started with cmd.exe /C in background and FOR captures all lines output by DIR to handle STDOUT. An error message output by DIR to handle STDERR on finding not any non-hidden file in current directory is redirected with 2>nul to device NUL to suppress it.
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
The DIR option /OS results in getting the list of non-hidden files output by DIR ordered by size with smallest first and largest last.
FOR would skip lines starting with a semicolon which means it would skip files which file name starts with ; which is in general possible. This is avoided by specifying with eol=| the vertical bar as end of line character which no file name can contain.
FOR would split up the lines into substring using normal space and horizontal tab as delimiter and would assign only first substring to loop variable I. File names can contain one or more spaces. Therefore delims= is used to define an empty list of delimiters which disable the line splitting behavior completely and get assigned to loop variable I the entire file name.
The IF condition if not "%FullBatchFileName%" == "%%~fI" compares case-sensitive the full qualified name of the batch file (drive + path + name + extension) with full qualified name of current file. This condition is only true if the current file is not the currently running batch file.
The next IF condition if %%~zI LSS %min.size% compares the file size of current file converted to a 32-bit signed integer with the specified file size also converted to a 32-bit signed integer. This file size comparison fails on files with 2 GiB or more as such a large file exceeds the maximum positive 32-bit signed integer value 2147483647.
The FOR loop is exited with goto DeletionDone on first line having a file size equal or greater the specified minimum size because of all further files output by DIR have definitely a file size equal or greater than the specified minimum size because of being output ordered by size from smallest to largest.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~f0 ... full qualified file name of argument 0 - the currently executed batch file.
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
popd /?
pushd /?
rem /?
set /?
setlocal /?
If you wanted to push ahead into PowerShell, the following script might work. When you are confident that the correct files will be deleted, remove the -WhatIf from the Remove-Item cmdlet.
$deldir = 'C:\Temp'
$minsize = 100000
$precious = 'Remove-UnderSize.ps1', 'Remove-UnderSize.bat'
Get-ChildItem -File -Path $deldir |
ForEach-Object {
if (-not ($precious -contains $_.Name)) {
if ($_.Length -lt $minsize) {
Remove-Item -Path $_.FullName -WhatIf
}
}
}
This script can be called from a cmd.exe bat file script.
powershell -NoProfile -File .\Remove-UnderSize.ps1

Run Autocad exe and load script file error

This is My first post in here
I need a help for your side I have made a batch file for run autocad exe and load a script file but give error when I run the batch file
#echo off
set KEY_NAME=HKCU\Software\Laxman Enterprises\Xpresslisp Tools
set VALUE_NAME=installpath
set FN=loadload
set FE=scr
FOR /F "tokens=2*" %%A IN ('REG.exe query "%KEY_NAME%" /v "%VALUE_NAME%"') DO (set pInstallDir=%%B)
set approot=%pInstallDir:~0,-1%
echo %approot%\%FN%.%FE%
"C:\Program Files (x86)\AutoCAD 2002\acad.exe" /b %approot%\%FN%.%FE%
pause
Error: while running batch file autocad opens and in commandline the script file not loading "Xpresslisp.scr": Can't find file."
and bellow one is working
script file loading without getting error
#echo off
set path=%USERPROFILE%
set fol=Documents
set NAME=1
set SUFFIX=scr
"C:\Program Files (x86)\AutoCAD 2002\acad.exe" /b %path%\%fol%\%NAME%.%SUFFIX%
pause
Regarding your second question in the comments...
Bellow command will create the text file and write the first line to it e.g. "some text" like in the command below.
Echo some text > full_path_to_txt_file
Command below will append new text to same file.
Echo some text >> full_path_to_txt_file
'>' char creates file and writes firs line
'>>' char append text
check that %path%\%fol%\%NAME%.%SUFFIX% returns the Full Path to the "Xpresslisp.scr" file !
if it does, inspect the Full Path and see if it contains any white spaces.
if it does, enclose the %path%\%fol%\%NAME%.%SUFFIX% with apostrophes
"%path%\%fol%\%NAME%.%SUFFIX%"
It may be something as simple as blindly removing the last character of the installpath without knowing for sure what it is, (doublequote or backslash?).
As there is unlikely to be multiple copies of any filename in the Xpresslisp Tools tree, I would suggest something like this:
#Echo Off
Set "KEY_NAME=HKCU\Software\Laxman Enterprises\Xpresslisp Tools"
Set "VALUE_NAME=installpath"
Set "FN=loadload"
Set "FE=scr"
(Echo=FILEDIA 0
Echo=(LOAD "C:\\loadmyfile.lsp"^)
Echo=FILEDIA 1)>%FN%.%FE%
For /F "Tokens=2*" %%A In ('Reg Query "%KEY_NAME%" /v "%VALUE_NAME%"') Do (
For /F "Delims=" %%C In ('Dir/B/S/A-D "%%~B"\"%FN%.%FE%" 2^>Nul') Do (
Start "" "%ProgramFiles(x86)%\AutoCAD 2002\acad.exe" /b "%%~C"))
This doesn't care if there is a trailing backslash or not and will only run the AutoCAD command if the file is there.

Batch file to sort files and list missing

I am trying to write a batch file that would read rows/lines from a txt file containing a list. The batch file would then copy the documents that match, and produce a list of missing files.
So far, the code successfully copies the files that it matches, but it also fills the "Missing.txt" file will exact contents of the input list, rather than simply the missing files.
#echo off
::Requests name of list file to be used by batch file
echo Enter list file name and press enter
set /p var=
mkdir %userprofile%\Desktop\%var%\
set /A lis=1
::Logic to search for files based on contents of list inputted by user at start.
for /f "tokens=*" %%i in (%var%.txt) DO (
call :processline %%i
IF NOT EXIST %%i (echo %%i>>%userprofile%\Desktop\%var%\Missing.txt)
)
pause
::Function called processline
::Assigns a string/value to variable "line"
::Copies a file with name = "line" to the user's desktop
::Renames the file to include a number reference, based on original list being searched
::Increments number for next file to be searched,copies and renamed
:processline
echo line=%*
xcopy /s %*.* %userprofile%\Desktop\%var%
move /Y %userprofile%\Desktop\%var%\%*.pdf %userprofile%\Desktop\%var%\%lis%_%*.pdf
set /A lis=%lis%+1
:eof
I suspect my problem is within the "for" logic, although there might be a way to input missing file names within the processline function.
Any help or advice would be much appreciated.
It's command order: :processline subroutine moves something, maybe including %%i file. I'd use next code snippet:
IF EXIST "%%~i" (
call :processline %%i
) ELSE (
>>"%userprofile%\Desktop\%var%\Missing.txt" echo %%i
)

Resources