Batch check for multiple file range - batch-file

i need to check if multiple files chronologically exist in a folder. I am having some issues and hope you can assist me.
There are some invoices that needed to be checked - with number starting from 13073713 to 13106972. The invoices contain a prefix "F" and the credit nots "G" for example "F13106972.pdf" and "G13106972.pdf" the suffix .pdf. What i am trying to do is loop through the folder and output all the missing ones chronologically into the log.txt. What am i doing wrong?
#echo off & setlocal
set "Ordner=%userprofile%\Desktop\test"
set "Log=%userprofile%\Desktop\Test\log.txt"
set /a from=13073713
set /a to=13106972
del "%Log%" 2 > nul
for /L %%i in(%from%,1,%to%)do (
if not exist "%Ordner%\F%i.pdf" echo F%%i
if not exist "%Ordner%\G%i.pdf" echo G%%i) >> "%Log%"

#echo off
setlocal enableextensions disabledelayedexpansion
set "Ordner=%userprofile%\Desktop\test"
set "Log=%userprofile%\Desktop\Test\log.txt"
set "from=13073713"
set "to=13106972"
(for /L %%i in (%from% 1 %to%) do (
if not exist "%Ordner%\F%%i.pdf" echo F%%i
if not exist "%Ordner%\G%%i.pdf" echo G%%i
)) > "%Log%"
Mainly typo errors. Changed/corrected from your code:
set /a in only needed to indicate to the parser that the value indicated to be stored in the variable contains some kind of arithmetic operation that needs to be evaluated. In batch files, at the end, all the values are strings. Not an error in your code (it works), but not needed.
The replaceable parameter in your for command is %%i. All the references to it must use the same double percent while inside a batch file. Some of your references were %i
The space after the in clause is needed
Log file deletion has been removed. All the for command is enclosed in a block (parenthesis) and redirected to the log file. If it exist, it will be overwritten.

Related

loop over an array in a bat script [duplicate]

This question already has answers here:
Arrays, linked lists and other data structures in cmd.exe (batch) script
(11 answers)
Closed 2 years ago.
I'm new to bat scripting and I wanted to use an iterative loop in my script (something like this in javascript for example)
for(var i=0;i<n;i++){
//my code here
console.log("my tab ["+i+"] is:"+tab[i];
}
So, basicaly this is my bat script in a file called exctract_excel_info.bat:
#ECHO OFF
::setlocal enabledelayedexpansion
:start
ECHO "Hi it's MIBE in this script i will list all the files with the extention xlsx or xls">log.txt
:start_loop
echo Listing all files in the current directory %cd% >log.txt
ECHO ================== ======================>>log.txt
set "AllowExt= *.xls"
ECHO the variable AllowExt in the first instruction %AllowExt%>>log.txt
set theFileName="NONE"
set /a i = 0
for %%a in (%AllowExt%) do (
set /a i = i + 1
::echo Found the file: "%%a">>log.txt
set theFileName[%i%]=%%a
)
:end_loop
ECHO ============================================>>log.txt
ECHO "The value of i is %i%">>log.txt
ECHO ============================================>>log.txt
for /L %%x in (1,1,%i%) do (
ECHO found the file %theFileName[%%x]%>>log.txt
)
ECHO ============================================>>log.txt
timeout /t 2
ECHO Yo the file %theFileName[0]% will be passed as a parameter
ECHO The array of files %theFileName%>>log.txt
:run_node
node main.js "%theFileName[0]%">>log.txt
timeout /t 2
:end
::PAUSE
I have a problem reading the value of the variable theFileName[i] in line 32
ECHO found the file %theFileName[%%x]%>>log.txt
This is the output (log.txt):
Listing all files in the current directory C:\Users\mibe\my bat
================== ======================
the variable AllowExt in the first instruction *.xls
============================================
"The value of i is 4"
============================================
So my problem is what is the proper way to read the value of the items inside theFileName array?
PS: when I comment the lines 31, 32, and 33:
for /L %%it in (1,1,"%i%") do (
ECHO found the file %theFileName[%%it]%>>log.txt
)
the script executes properly and get the value of %theFileName[0]%
The following is a basic example of what I think you're trying to do, up to a point.
The problem is that because you've not told us what exactly you're intending to do with those similarly named variables, I cannot include the specific methodology for doing so. I have therefore just output the defined variable names along side their value strings.
#SetLocal EnableExtensions DisableDelayedExpansion
#For /F "Delims==" %%G In ('"(Set File[) 2> NUL"') Do #Set "%%G="
#Set "i=0" & For /F Delims^= %%G In (
'"(Set PATHEXT=) & "%__APPDIR__%where.exe" ".:*.xlsx" ".:*.xls" ".:*.csv" 2> NUL | "%__AppDir__%sort.exe""'
) Do #(Set /A i += 1 & SetLocal EnableDelayedExpansion
For %%H In (!i!) Do #EndLocal & Set "File[%%H]=%%~nxG")
#If Defined File[1] For /L %%G In (1,1,%i%) Do #(SetLocal EnableDelayedExpansion
Echo File[%%G]=!File[%%G]! & EndLocal)
#Pause
The code above should define individual variables, each containing the string value of a file in the current directory, which has an extension of either .xlsx, .xls, or .csv.
When I first looked at your question I initially thought that you were intending to pass each file name together as multiple arguments to your node command.
If that is what you're actually intending to do, then I'd assume the following example would suit your purposes better.
#SetLocal EnableExtensions DisableDelayedExpansion
#Set "FileList="&For /F Delims^= %%G In (
'"(Set PATHEXT=) & "%__APPDIR__%where.exe" ".:*.xlsx" ".:*.xls" ".:*.csv" 2> NUL | "%__AppDir__%sort.exe""'
) Do #If Not Defined FileList (Set "FileList="%%~nxG"") Else (SetLocal EnableDelayedExpansion
For /F Delims^=^ EOL^= %%H In ("!FileList!") Do #EndLocal & Set "FileList=%%H "%%~nxG"")
#If Defined FileList Echo %%FileList%%=%FileList%
#Pause
The code above should define a single variable, containing the space separated, and doublequoted, string values, of each file in the current directory, which has an extension of either .xlsx, .xls, or .csv.
Please note that there is a command line length limitation so be aware that your value could become truncated.
In both examples:
The last line, #Pause, is included only to prevent premature closure of the cmd window, should you not be testing this from the CLI. (You can safely remove it if you are).
I assumed you wanted only the filenames without their paths, in the variable values. Should you wish for the full paths, just change %%~nxG in your chosen example code to %%G.
BTW, I used sort.exe against the returned files, because you mentioned array, and IMO an array should be ordered. (If you do not need that functionality, you could remove | "%__AppDir__%sort.exe" from your chosen example code).
Please note that there is a limit to the size of the environment, so be aware that if you have many matching files, they have long filenames, include paths etc. you may reach or exceed that limitation.
Having provided some examples for you, I'm not sure why you could not just iterate your directory, and create an array of those files, directly using .js, (off topic).

I was given a .BAT script and I received an error of "%%X" is unexpected can someone tell me what I am doing wrong?

In short I was provided this code by my professor, im getting an error where it says "%%X" the output says %%X unexpected error.
SETLOCAL ENABLEDELAYEDEXPANSION
SET CURRENT_DIR=%CD%
SET DIR_NAME=%CURRENT_DIR%\CIS153
SET COUNTER=1
MKDIR %DIR_NAME%
FOR /F "DELIMS=" %%X IN (MyData.txt) DO (
ECHO %%X > myFile!COUNTER!.txt
SET /A COUNTER=!COUNTER!+1
)
What I expect the the code to do is make a directory called CIS153
and based on the content from MyData.txt it'll create a new directory and write it to an entire new file.
#Magoo is right. This script must be in a file. Use Notepad.exe or another editor to create a file.
There is also some quoting that should be added. Use quotes around the SET command to ensure that invisible characters like SPACE and TAB are not at the end of the value.
Also, paths need to be quoted since they may contain SPACE or other special characters.
Checking to see if a directory exists before making it will avoid an error message if it already exists.
Finally, I note that while it does create a directory, there is nothing that sets it as the current directory. The result is that the "myfile*.txt" files will be created in the current directory and not in the newly created directory.
=== CIS153.bat
SETLOCAL ENABLEDELAYEDEXPANSION
SET "CURRENT_DIR=%CD%"
SET "DIR_NAME=%CURRENT_DIR%\CIS153"
SET "COUNTER=1"
IF NOT EXIST "%DIR_NAME%" (MKDIR "%DIR_NAME%")
rem CD "%DIR_NAME%" ???
FOR /F "DELIMS=" %%X IN (MyData.txt) DO (
ECHO %%X > myFile!COUNTER!.txt
SET /A COUNTER=!COUNTER!+1
)

A script that counts and prints every ocurrence of not any file inside a common subfolder in a specific path

Although I'm really a newbie in this field, I want to accomplish a task in batch scripting: There is a determinate folder of company contracts in a determinate path, each of this folders (approx. 400) has a common folder (2016) where there might be a file indicating there has been an inspection in this year. What i want is to print every company folder that has not any file in the common 2016 folder and a count of the times this happens.
This is what i have (and does not work at all):
set c=0
for %i /d in (*) do
for %j in ($%i\2016\*) do
if (%j==NUL) then (#echo $%i c+=1 echo %c)`
If you just want to know if there is a file in the 2016 directory you can do this:
#echo off
SetLocal EnableDelayedExpansion
set count=0
for %%i /d in (*) do (
REM first unset variable
set files=
for %%j in (%%i\2016\*) do (
REM will set variable each time a file is encountered
set files=present
)
if not DEFINED files (
REM No files in directory 2016
echo %%i
set /a count+=1
echo !count!
)
)
EndLocal
exit /b 0
I don't see why you use $ before each %i. If you execute this code from the command line use one % for the loop variables i and j. But in a batch-script you'll have to use two of them (%%i, %%j).
Another thing, c+=1 won't work except if you use set /a.
I used delayed expansion because each block code ( between (...)) is parsed as one single command (as if it was all on one line with && between the commands inside the block) and you can't just assign a new value to a variable and read that new value in the same command. That's also the reason why I use !count! instead of %count% (which will give the value before the block). If you'd rather not use delayed expansion, remove the SetLocal EnableDelayedExpansion and replace echo !count! with call echo %%count%% (is another way to read a new value in the same command)
Also, be aware that each echo will end its output with a carriage retur and a newline. So each echo will result in a new line of output.

How to find and replace all files in a folder using a dynamic value

I'm having a few html files where I need to add the pagename as a tag value. Plenty of tools to do mass find and replace, but than you are restricted to a static text, while I need to add the actual filename.
It works perfectly fine on a single file, but if I start to loop into a directory it goes wrong, and I'm not able to figure out where things go wrong.
Doing this on a single predefined file works as expected :
#echo off & setLocal enableDELAYedexpansion
rem Create tmp file to store modified information
set tmpFile=%CD%\test\tmp.txt
set myFile=%CD%\test\test.html
set page=test
rem delete current tmp file
if exist "%tmpFile%" del /f /q "%tmpFile%"
rem find and replace values
set search="container"
set replace="container_!page!"
rem loop through all the lines and replace the string in question
for /F "tokens=*" %%a in (%myFile%) do (
set myLines=%%a
set myLines=!myLines:%search%=%replace%!
echo !myLines! >> %tmpFile%
)
rem update current file with updated content
type !tmpFile! > !myFile!
)
pause
The above nicely finds my string, and replaces it with the one I want (though still static in this case)
But if I want the same logic to loop through more files it goes wrong. This is the code I use :
#echo off & setLocal enableDELAYedexpansion
rem Create tmp file to store modified information
set tmpFile=%CD%\test\tmp.txt
rem switch to test folder
cd %CD%/test
rem Start the loop
For /R %%F in (*.html) do (
rem get page name
set page=%%~nxF
set MyFile=%%F
rem delete current tmp file
if exist "%tmpFile%" del /f /q "%tmpFile%"
rem find and replace values
set search="container"
set replace="container_!page!"
rem loop through all the lines and replace the string in question
for /F "tokens=*" %%a in (%%F) do (
set myLines=%%a
set myLines=!myLines:%search%=%replace%!
echo !myLines! >> %tmpFile%
)
rem update current file with updated content
type !tmpFile! > !myFile!
)
pause
This basically doesn't do anything, I've been trying some otehr variations but these result in either empty pages or pages that contain myLines= as a literal string.
What am I overlooking here ?
[EDITED AREA]
I've managed to get it working partially, but have strange unwanted side effects.
Not using search / replace parameters but using it directly in the replace parts as follows works :
for /F "tokens=*" %%a in (%%F) do (
set myLines=%%a
set "myLines=!myLines:container=container_%%~nF!"
echo !myLines! >> %tmpFile%
)
This replaces container with container_pagename as I wanted , BUT it also removes all esclamation marks on my htm, which is quite annoying, as it ruins all the comments on the page.
so <!-- comment -->
becomes <-- comment -->
Any clue where it goes wrong, or why using parameters doesn't work for me ?
type !inputfile! > !tmpFile!
might be a problem. Suggest you consider what it does...
I'd also change
set var="value"
to
set "var=value"
The first assigns a quoted value to var; the second ensures that stray spces on the line are not included in value assigned to var

Creating multiple files using batch files

Hi Can anyone help me out in this problem.
I need to create multiple file?? i give with any example. In some folder, say Folder Records.
"Record" folder contain 1 file by name "example2tought1023.au" . i need to generate same file contains, multiple time just by increasing the numbers.
i should get result like this example2tought1023.au example3tought1024.au example4tought1025.au example5tought1026.au
This is what I currently have:
SET count=9
SET filename_1=example
SET filename_2=thought
SET extension=.au
SET start_1=2
SET start_2=1023
SET source=%filename_1%%start_1%%filename_2%%start_2%%extension%
FOR /L %%i IN (1, 1, %count%) DO (
REM These two lines do not work!
SET /a n=%start_1%+%%i
SET /a number_2=%start_2% + %%i
SET destination=%filename_1%%number_1%%filename_2%%number_2%%extension%
ECHO %destination%
REM COPY %source% %destination%
)
PAUSE
but the lines in the FOR /L loop do not work
You have mis-identified which lines are not working :-)
The problem you are having relates to when variables are expanded. Normal expansion using percents occurs when the line is parsed, and your entire FOR statement, including the parenthesised DO clause, is parsed in one go. So the following line
SET destination=%filename_1%%number_1%%filename_2%%number_2%%extension%
is seeing the values of %number_1% and %number_2% that existed before the loop was executed. Obviously not what you want. The solution is simple - you need to use delayed expansion (the value at run time instead of parse time). You do that by 1st enabling delayed expansion using setlocal enableDelayedExpansion, and then use !number_1! instead of %number_1%.
You are not consistent with your variable names (n vs number_1).
I think you want to count from 0 to count-1 instead of from 1 to count.
You do not have to explictly expand the variable when using a variable in a SET /A expression. You can simply use the variable name without percents or exclamations. But this only works with the SET /A command.
You can also perform multiple computations and assignments with a single SET /A command by using a comma between each assignment.
#echo off
setlocal enableDelayedExpansion
REM counts from 0 to count, so 8 = 9 copies
set count=8
set filename_1=example
set filename_2=thought
set extension=.au
set start_1=2
set start_2=1023
set source=%filename_1%%start_1%%filename_2%%start_2%%extension%
for /L %%i in (0, 1, %count%) do (
set /a "number_1=start_1+%%i, number_2=start_2+%%i"
set destination=%filename_1%!number_1!%filename_2%!number_2!%extension%
echo !destination!
REM copy %source% !destination!
)
pause

Resources