Batch file commands - Findstr, splitting and file name variables - batch-file

I'm kind of new to batch commands and have been trying to automate something we do manually. I have a log file that is downloaded every day, then I search for certain items in it using Findstr (output to another file) and then split what was found into smaller files.
I'm having trouble with making file names and file name variables and using it throughout my code. The splitter code was given to me, so I'm just trying to incorporate Findstr into it. Any tips or see what I'm doing wrong?
Example:
Campaign ID: 1234
Campaign Name: Pepsi
Impression Filename: 10-06-16_file.log
Day of week: 2
It will look through 10-06-16_file.log for any rows with Campaign ID 1234 and output them to fnd_10-06-16_file.log.
If fnd_10-06-16_file.log filesize is greater than 177000kb then split the file into smaller files with name 2SplitFile1_Pepsi.log, 2SplitFile2_Pepsi.log, 2SplitFile3_Pepsi.log, etc.
setlocal ENABLEDELAYEDEXPANSION
#echo off
REM Ask for Campaign information to find
SET /P campaignid="Campaign ID(s): "
SET /P campaignname="Campaign Name: "
SET /P impressionfile="Impression Filename: "
SET /P dayofweek="Day of week: "
SET fnd_impressionfile=%campaignname%_%impressionfile%
SET maxbytesize=177000
SET fnd_impressionfile_sz=%%~zfnd_impressionfile
REM Find campaigns inside log file
findstr "%campaignname%" %impressionfile% > %fnd_impressionfile%
REM Split log file if greater than 177000 kb
if fnd_impressionfile_sz > maxbytesize (
REM Edit this value to change the name of the file that needs splitting. Include the extension.
SET BFN=%fnd_impressionfile%
REM Edit this value to change the number of lines per file.
SET LPF=1000000
REM Edit this value to change the name of each short file. It will be followed by a number indicating where it is in the list.
SET SFN=SplitFile
REM Do not change beyond this line.
SET SFX=%BFN:~-3%
SET /A LineNum=0
SET /A FileNum=1
For /F "delims=" %%l in (%BFN%) Do (
SET /A LineNum+=1
echo %%l >> %dayofweek%%SFN%!FileNum!_%campaignname%.%SFX%
if !LineNum! EQU !LPF! (
SET /A LineNum=0
SET /A FileNum+=1
)
)
)
endlocal
pause

First, change SET fnd_impressionfile_sz=%%~zfnd_impressionfile to FOR %%a in (%fnd_impressionfile%) DO SET fnd_impressionfile_sz=%%~za
Then, double check you maxbytesize. Your description says kb, but the batch implies byte. fnd_impressionfile_sz contains the byte value.
The other thing I see is there you're using the redirection operator > in if fnd_impressionfile_sz > maxbytesize. You should change it to GTR or GEQ. See HELP IF.

Related

Batch: Read out number, iterate and write back

I want a text file with just a number that is getting iterated every time i use the batch file. I tried this so far but its not working...
set laufende_nr=0
if not exist echo %laufende_nr% > %def_log_dir%\laufende_nr.tmp
for /L %%i in (%def_log_dir%\laufende_nr.tmp) set laufende_nr=%%i
echo %laufende_nr%
set /a laufende_nr+=laufende_nr
echo %laufende_nr_neu% > %def_log_dir%\laufende_nr.tmp
Here's some quick example code for you to study:
Set "laufende_nr="
If Exist "%def_log_dir%\laufende_nr.tmp" (
Set/P "laufende_nr="<"%def_log_dir%\laufende_nr.tmp"
)
If Not Defined laufende_nr Set "laufende_nr=0"
Echo %laufende_nr%
Set/A laufende_nr+=1
(Echo %laufende_nr%)>"%def_log_dir%\laufende_nr.tmp"
Enter Set/?, If/? & Echo/? as necessary for respective information.
EditIf you have a relative directory named Set which contains an executable file named either A or P, then you would be best advised to change Set/A to Set /A and/or change Set/P to Set /P as necessary.

split .csv file using a batch file

I have a huge csv file with more columns than allowed in excel so i need to split the file into 2 in order to use it.
I found a code which i can put in a batch file and it works too but the problem is if data is not available in a cell it takes data from the next available cell.
Also it is taking a long time.
Please let me know how the code can be edited?
#echo off
setlocal ENABLEDELAYEDEXPANSION
REM Edit this value to change the name of the file that needs splitting. Include the extension.
SET BFN=BigFile.csv
REM Edit this value to change the number of lines per file.
SET LPF=5000
REM Edit this value to change the name of each short file. It will be followed by a number indicating where it is in the list.
SET SFN=SplitFile
REM Do not change beyond this line.
SET SFX=%BFN:~-3%
SET /A LineNum=0
SET /A FileNum=1
For /F "delims==" %%l in (%BFN%) Do (
SET /A LineNum+=1
echo %%l >> %SFN%!FileNum!.%SFX%
if !LineNum! EQU !LPF! (
SET /A LineNum=0
SET /A FileNum+=1
)
)
endlocal
Pause
Also my company does not allow me to download any csv splitters or any other data.
All help would be appreciated.

How to make my user input as a variable to make a folder

(c)ToTheMaker
I found this code here and I'm going to use it but the only problems is I want it to have a user input that will create the folders
For example: "Enter number of folders:"
The value which the user will input will be used as a variable that will create the folders. How am I going to do that?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET groupsize=10
SET n=1
SET nf=0
FOR %%f IN (*.txt) DO (
IF !n!==1 (
SET /A nf+=1
MD Cake_!nf!
)
MOVE /Y "%%f" Cake_!nf!
IF !n!==!groupsize! (
SET n=1
) ELSE (
SET /A n+=1
)
)
ENDLOCAL
PAUSE
Executing in a command prompt window either help set or set /? results in printing several help pages into the console window for command SET which should be read carefully. The help explains also set /P for prompting user for a value or string.
#echo off
set "FolderCount=1"
set /P "FolderCount=Enter number of folders (default: %FolderCount%): "
for /L %%N in (1,1,%FolderCount%) do md "Folder%%N"
set "FolderCount="
This little batch code defines the environment variable FolderCount with value 1 as default value which is used when the user hits just key RETURN or ENTER on prompt.
The user is asked next for the number of folders to create. The string entered by the user is assigned to environment variable FolderCount. The user hopefully enters a positive number and not something different.
The FOR loop creates the folders in current directory with name Folder and the current number appended which is automatically incremented by 1 on each loop run starting with value 1.
The last line deletes the environment variable FolderCount not needed anymore.
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.
echo /?
for /?
md /?
set /?
Edit: The final batch code for the entire task with moving the text files, too.
#echo off
rem Delayed expansion required for variable FolderIndex in FOR loop.
rem Command setlocal additionally creates a new environment variable
rem table with copying all existing variables to the new table.
setlocal EnableDelayedExpansion
rem Ask the batch user for number of subfolders to create and create them.
set "FolderCount=1"
set /P "FolderCount=Enter number of folders (default: %FolderCount%): "
for /L %%N in (1,1,%FolderCount%) do md "Folder%%N"
rem Move all *.txt files from current folder into the created subfolders.
set "FolderIndex=0"
for %%F in (*.txt) do (
set /A FolderIndex+=1
move /Y "%%~F" "Folder!FolderIndex!\%%~nxF"
if !FolderIndex! == %FolderCount% set "FolderIndex=0"
)
rem Restore previous environment which results in destroying
rem current environment table with FolderIndex and FolderCount.
endlocal

Batch check for multiple file range

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.

How do I exclude specific file names from an MS DOS dir list?

I am creating an MS DOS batch script that needs to list every .bat file in the current directory, but not show autoexec.bat or other utilities or systems .bat files that shouldn't be run by the user.
I currently have DIR "*.bat" /B /P
This lists all .bat files appropriately, but it shows autoexec.bat. How would I exclude that from the list? Also slightly important, how could I chop off the file extensions and show more than the 7-characters DOS limits files to?
Constraints: I am not able to use a DOS version above WinME. That is the version I am using.
Thanks for any help.
EDIT:
There is plenty of information on the internet about doing this, but it is all in the windows command processor, not MS DOS. Please understand that DOS and the Command Prompt are not the same thing.
#echo off
setlocal EnableDelayedExpansion
rem Add more names separated with slashes here:
set exclude=/autoexec/
for %%a in (*.bat) do (
if "!exclude:/%%~Na/=!" equ "%exclude%" (
echo %%~Na
)
)
EDIT: Some explanations added
Batch file processing is slow, so you should use techniques that allows a Batch file to run faster. For example:
Try to use the minimum lines/commands to achieve a certain result. Try to avoid external commands (*.exe files) like find, findstr, fc, etc. specially if they work on small amounts of data; use if command instead.
Use for %%a in (*.bat)... instead of for /F %%a in ('dir /B *.bat').... The second method requires to execute cmd.exe and store its output in a file before for command can process its lines.
Avoid pipes and use redirections instead. A pipe require the execution of two copies of cmd.exe to process the command at each side of the pipe.
A simple way to check if a variable contain a given string is trying to delete the string from the variable: if the result is different then the string exists in the variable: if "!variable:%string%=!" neq "%variable%" echo The string is in the variable.
Previous method may also be used to check if a variable have anyone of a list of values: set list=one two three, if "!list:%variable%=!" neq "%list%" echo The variable have one value from the list. If the values of the list may have spaces, they must be separated by another delimiter.
EDIT: New version added as answer to new comments
The easiest way to pause one page at a time is to use more filter this way:
theBatchFile | more
However, the program must reorder the output in order to show it in columns. The new version below achieve both things, so it does not require more filter; you just need to set the desired number of columns and rows per page.
#echo off
setlocal EnableDelayedExpansion
rem Add more names separated with slashes here:
set exclude=/autoexec/
rem Set the first two next variables as desired:
set /A columns=5, rows=41, wide=(80-columns)/columns, col=0, row=0
rem Create filling spaces to align columns
set spaces=
for /L %%a in (1,1,%wide%) do set spaces= !spaces!
set line=
for %%a in (*.bat) do (
if "!exclude:/%%~Na/=!" equ "%exclude%" (
rem If this column is less than the limit...
set /A col+=1
if !col! lss %columns% (
rem ... add it to current line
set name=%%~Na%spaces%
set "line=!line!!name:~0,%wide%! "
) else (
rem ... show current line and reset it
set name=%%~Na
echo !line!!name:~0,%wide%!
set line=
set /a col=0, row+=1
rem If this row is equal to the limit...
if !row! equ %rows% (
rem ...do a pause and reset row
pause
set row=0
)
)
)
)
rem Show last line, if any
if defined line echo %line%
Antonio
attrib +h autoexec.bat
should hide autoexec.bat and it should thus not appear in the list
DIR "*.bat" /B /P | find /v "autoexec" | for %i in (*.bat) do #echo %~ni
Using for to process each file name individually:
setlocal enabledelayedexpansion
for /f %%i in ('dir "*.bat" /b') do (
set system=0
if "%%i"=="autoexec.bat" set system=1
if "%%i"=="somesystem.bat" set system=1
if !system!==0 echo %%i
)
Another method without variables:
for /f %%i in ('dir "*.bat" /b') do call :test %%i
goto continue
:test
if "%1"=="autoexec.bat" goto :eof
if "%1"=="somesystem.bat" goto :eof
echo %1
goto :eof
:continue
For both, you can add new filenames to exclude from the list.

Resources