Add delimiter to txt file from batch script in Windows - database

I have a text.txt file that is filled with data that is not separated by a delimiter. I need to add a delimiter based on columns in the text file.
The data currently looks like
00067800000000000000000000N00006N 00000125463150050000012546315012
00067800000000000000000000N00006N 00000125463150810000012546315098
and I need to be add a delimiter such as "," at specific columns in the text so it comes out looking like.
000678,0000000,000000,0000000,N,00006,N, ,00000,12546315005,00000,12546,315012
000678,0000000,000000,0000000,N,00006,N, ,00000,12546315081,00000,12546,315098
I would like to create a batch file that goes through and adds the delimiter , at each column I need it for every line in the file.
Is this possible?
Thanks in advance!

#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q39666479.txt"
SET "outfile=%destdir%\outfile.txt"
:: set delimiter and read column-sizes from supplied command-line
SET "delimiter=,"
CALL :colsize %*
(
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
SET "line=%%a"
CALL :report
)
)>"%outfile%"
GOTO :EOF
:colsize
SET "magic="
:: offset position
SET /a size=0
:colsizelp
IF DEFINED magic (
SET "magic=%magic%%delimiter%`line:~%size%,%1`"
) ELSE (
SET "magic=`line:~%size%,%1`"
)
SET /a size +=%1
SHIFT
IF "%1" neq "" GOTO colsizelp
SETLOCAL enabledelayedexpansion
SET "magic=!magic:`=%%!"
endlocal&SET "magic=set "line=%magic%""
GOTO :eof
:report
CALL %magic%
ECHO %line%
GOTO :eof
You would need to change the settings of sourcedir, filename1 and destdir to suit your circumstances.
I used a file named q39666479.txt containing your data for my testing.
Produces the file defined as %outfile%
Run as thisbatchname 6,7,6,7,1,5,1,1,5,11,5,5,6
to produce the above result. Each number is simply the column-width.
Essentially, build the string magic as appropriate substring commands strung together to assemble the output line as required. With each line from the file, execute the magic command and echo the result.

Related

Creating a batch file to prompt for response and replace lines of text in a text or .ini file

I have gotten the batch file to work for the first line, however when I try to add an additional FOR loop to get the next line of text it actually copies or duplicates the text instead of replacing it.
currently the batch file will not even change the .txt file.
Code below --
::Find and Replace script allows the user to
::define a file path, file name and a string
::to find and replace so as to create a new file.
::
::Original file is backed up with an added extension of *.bak, in case
::the user finds the need to go back to the original.
#echo off
::Use the path from whence the script was executed as
::the Current Working Directory
set CWD=%~dp0
::***BEGIN MODIFY BLOCK***
::The variables below should be modified to the
::files to be changed and the strings to find/replace
::Include trailing backslash in _FilePath
set _FilePath=C:\
set _FileName=Password1.txt
::_WrkFile is the file on which the script will make
::modifications.
set /P Password="What is the admin Password?"
set /P AuditPassword="What is the Audit Password?"
set oldPass="cmspassword=Password1"
set OldAudit="existingauditingdbpassword=Password1"
set CMSAdmin="cmspassword="
set CMSAudit="existingauditingdbpassword="
set OldStr=%oldPass%
set OldStr2=%OldAudit%
set NewStr="%CMSAdmin%%Password%"
set NewStr2="%CMSAudit%%AuditPassword%"
::***END MODIFY BLOCK***
::Set a variable which is used by the
::search and replace section to let us
::know if the string to be modified was
::found or not.
set _Found=Not found
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
if not exist "%_FilePath%%_FileName%" goto :NotFound
echo Searching for %OldStr% string...
echo.
for /f "usebackq tokens=*" %%a in ("%_FilePath%%_FileName%") do (
set _LineChk=%%a
if "!_LineChk!"==%OldStr% (
SET _Found=Found
SET NewStr=!NewStr:^"=!
echo !NewStr!
) else (echo %%a)
)>>"%_FilePath%%_FileName%" 2>&1
for /f "usebackq tokens=*" %%b in ("%_FilePath%%_FileName%") do (
set _LineChk=%%b
if "!_LineChk!"==%OldStr2% (
SET _Found=Found
SET NewStr2=!NewStr2:^"=!
echo !NewStr2!
)
)
echo.
:Exit
exit /b

Batch: convert pipe delimited text file to comma delimited csv file

I have a .txt file like this:
Customer Number||Customer Name||Partner Number||Partner Name||Customer Country
1ABC||Jame||1234||Anny||USA
2DEF||Susan||5678||Prissy||UK
My output should be a .csv file with no empty columns.
This is what I tried:
#echo off
setlocal disableDelayedExpansion
set input="C:\a.txt"
set output="C:\Customer_Pipe.csv"
>%output% (
for /f "tokens=*" %%a in ('input"') do (
set line=%%a
setlocal enableDelayedExpansion
echo "!line:|=","!">>"%~2"
)
)
If you want to read the file stored in variable INPUT, you need to read it as %INPUT% to do that (you stated INPUT literally, with odd quotation). When you specify '' within the set of for /F, the part within () is interpreted as a command rather than a file, so for /F tries to execute command input which cannot be found and so the script fails. I stringly recommend to put "" around the specified file, together with the usebackq option, in order to avoid trouble with white-spaces in paths/file names.
If you want to write into the file stored in variable OUTPUT, you must not redirect the echo to somewhere else (you placed >>"%~2" in the code).
Here is the code as I would write it:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define constants here:
set "INPUT=%~1"
set "OUTPUT=%~2"
if not defined INPUT exit /B 1
if not defined OUTPUT set "OUTPUT=con"
> "%OUTPUT%" (
for /F usebackq^ delims^=^ eol^= %%L in ("%INPUT%") do (
set "LINE=%%L"
setlocal EnableDelayedExpansion
echo(!LINE:^|^|=,!
endlocal
)
)
endlocal
exit /B
The input file for the batch program must be provided as the first command line argument. The second argument (optional) is the output file.
Note that this script does not check whether the input data contains , characters, which impact the way the converted file is treated. If you want to put quotation marks around all fields of the returned CSV data to avoid data interpretation troubles, replace the above echo command line by:
echo("!LINE:||=","!"
The output data (with the original echo command line) looks like this:
Customer Number,Customer Name,Partner Number,Partner Name,Customer Country
1ABC,Jame,1234,Anny,USA
2DEF,Susan,5678,Prissy,UK
The output data with the modified echo command line looks like this:
"Customer Number","Customer Name","Partner Number","Partner Name","Customer Country"
"1ABC","Jame","1234","Anny","USA"
"2DEF","Susan","5678","Prissy","UK"
There are two problems in your code.
1)
You use setlocal EnableDelayedExpansion, that's a good idea, but you have to close it with endlocal else you get an error after ~32 setlocals.
2)
Your replace functions looks a bit odd.
You add some quotes, they will be part of the output later.
You could try this.
echo(!line:^|^|=,!
At all
>%output% (
for /f "tokens=*" %%a in (%input%) do (
set "line=%%a"
setlocal EnableDelayedExpansion
set "line=!line:||=,!"
(echo(!line!)
endlocal
)
)

How to choose one of multiple actions based on file extension, in batch

I'm an amateur on the usage of the FOR command. I need a batch file that will run one of 5 file conversion tools based on a file's extension. I want to drop a file onto the batch file icon and have it converted.
Since my list is huge, I can't use nested IF's.
What I've tried so far:
#ECHO OFF
SET cadfile=.dwg .dxf .dwf
SET gsfile=.ps .eps .epi .epsp
SET xxxxxx=.xx .xx and goes on
FOR %%~x1 in (%cadfile%) do (
Do some action
FOR %%~x1 in (%gsfile%) do (
Do some other action
)
)
The %%~x1 variable is used for file extension of file, which dragged and dropped over the batch file.
(edited to make more clear)
FOR %%a in (%cadfile%) do (
if /i "%~x1"=="%%a" some_action "%~1"
)
... and follow the bouncing ball for the rest of the utilities/lists
I think this will work for you. It looks through all your groups of extensions in a single For loop and when the matching extension is found, calls a label where you can do the conversion and any related tasks. You'll need to finish the "groupN" variables and labels.
#echo off
SETLOCAL EnableDelayedExpansion
set file="%1"
set ext=%~x1
:: Set the 5 groups of extensions that have different converters
set group1=.dwg, .dxf, .dwf
set group2=.ps, .eps, .epi, .epsp
For %%A in (1 2 3 4 5) do (
set groupnum=group%%A
call set thisgroup=%%!groupnum!%%
:: Look for extension in this group
echo.!thisgroup!|findstr /i /C:"%ext%" >nul 2>&1
if not errorlevel 1 call :group%%A
:: else go loop next group
)
echo Extension not found in any group &pause &goto end
:group1
echo group1 file to convert is %file%
goto end
:group2
echo group2 file to convert is %file%
goto end
:end
pause
exit
The following method allows you to easily add and modify your list of extensions/applications. Please note that you just need to edit the values placed inside the first FOR command; the rest of the program is the solution you don't need to care of...
#echo off
setlocal EnableDelayedExpansion
rem Define the list of extensions per application:
rem (this is the only part that you must edit)
for %%a in ("cadfile=.dwg .dxf .dwf"
"gsfile=.ps .eps .epi .epsp"
"xxxxxx=.xx .xx1 .xx2") do (
rem The rest of the code is commented just to be clear,
rem but you may omit the reading of this part if you wish
rem Separate application from its extensions
rem and create a vector called "ext" with an element for each pair
for /F "tokens=1,2 delims==" %%b in (%%a) do (
rem For example: %%b=cadfile, %%c=.dwg .dxf .dwf
for %%d in (%%c) do set "ext[%%d]=%%b"
rem For example: set "ext[.dwg]=cadfile", set "ext[.dxf]=cadfile", set "ext[.dwf]=cadfile"
rem In the next line: set "ext[.ps]=gsfile", set "ext[.eps]=gsfile", etc...
)
)
rem Now process the extension of the file given in the parameter:
if defined ext[%~x1] goto !ext[%~x1]!
echo There is no registered conversion tool for %~x1 extension
goto :EOF
:cadfile
echo Execute cadfile on %1 file
rem cadfile %1
goto :EOF
:gsfile
echo Execute gsfile on %1 file
rem gsfile %1
goto :EOF
etc...
If each conversion tool is executed in the same way and don't require additional parameters (just the filename), then you may omit the individual sections and directly execute the conversion tools this way:
if defined ext[%~x1] !ext[%~x1]! %1
For further explanations on array concept, see this post.

Batch file for loop unable to assign values from external file

So, I've got this basic text file called prev_batch.cfg that I want a batch script to read. prev_batch.cfg is a single line of text, but tokens are delimited with a comma. It looks something like:
apples,oranges,bananas,grapes,strawberries
I'd like each of those tokens to go into a specific variable I have setup in a for loop. The problem is only the first variable gets set within the loop. Nothing else. I want all the variables to be set to the tokens found within the delimited list in the .cfg file.
Here is what my batch script looks like up until the close of the FOR loop:
#ECHO ON
setlocal EnableDelayedExpansion
SET JOB=%1
SET USER=%2
SET ASSETROOT=%3
:: Read all the arguments for this batch script from external text file
FOR /F "delims=," %%a IN (%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg) do (
SET JOB=%%a
SET USER=%%b
SET TEMPLATE=%%c
SET ASSETROOT=%%d
SET SHAREADDR=%%e
SET SHARENAME=%%f
SET SHAREDRIVE=%%g
SET SHAREUSER=%%h
SET SHAREPASS=%%i
)
I'm running the batch file and passing three command line parameters into it. I'm outputting the echo of the batch when it runs to a log file. And this is what I'm seeing:
C:\Windows\system32>setlocal EnableDelayedExpansion
C:\Windows\system32>SET JOB=99D0FAA9-22B8-4FE7-9321-21F5587E8177
C:\Windows\system32>SET USER=10
C:\Windows\system32>SET ASSETROOT=C:\app
C:\Windows\system32>FOR /F "delims=," %a IN (C:\app\users\10\99D0FAA9-22B8-4FE7-9321-21F5587E8177\prev_batch.cfg) do (
SET JOB=%a
SET USER=%b
SET TEMPLATE=%c
SET ASSETROOT=%d
SET SHAREADDR=%e
SET SHARENAME=%f
SET SHAREDRIVE=%g
SET SHAREUSER=%h
SET SHAREPASS=%i
)
C:\Windows\system32>(
SET JOB=99D0FAA9-22B8-4FE7-9321-21F5587E8177
SET USER=%b
SET TEMPLATE=%c
SET ASSETROOT=%d
SET SHAREADDR=%e
SET SHARENAME=%f
SET SHAREDRIVE=%g
SET SHAREUSER=%h
SET SHAREPASS=%i
)
try this:
FOR /F "usebackq tokens=1-9 delims=," %%a IN ("%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg") do (
SET JOB=%%a
SET USER=%%b
SET TEMPLATE=%%c
SET ASSETROOT=%%d
SET SHAREADDR=%%e
SET SHARENAME=%%f
SET SHAREDRIVE=%%g
SET SHAREUSER=%%h
SET SHAREPASS=%%i
)
[addition by PW in response to supplementary question]
SET init=Y
SET "fields=JOB USER TEMPLATE ASSETROOT SHAREADDR SHARENAME SHAREDRIVE SHAREUSER SHAREPASS"
FOR /F "usebackq" %%a IN ("%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg") do (
IF DEFINED init FOR %%i IN (%fields%) DO SET "%%i="
SET init=Y
FOR %%i IN (%fields%) DO IF DEFINED init IF NOT DEFINED %%i SET "%%i=%%a"&SET "init="
)
To read from sequential lines, the tokens and delims clauses are not required since there's only one string on each line BUT that one string needs to be applied to various variables.
Complicating the matter is the fact that variables that need to be set are used in the filename being read to set them.
Hence, the init flag is set non-empty initially; the variables are set once the first data line is read.
The next not-yet-set target variable is then set and the init flag cleared to ensure only one variable is set per line read.
okay, I like batch files and this one had me going for a while. You've told it that you only want %%a so that's what you're getting.
As Endoro said (I was typing the same answer when he posted), including the "tokens" keyword tells it which tokens you want.
Token %%a, obviously is the first, but by also telling the command processor that you want tokens 1-9 it separates and assigns them to next alphabetical 'variable'.
And in this case, usebackq is superfluous
There is another approach to solve this problem via an array of variable names. This method have the advantage that any modification to the list of variables (the number of variables, their names, their positions, etc) is made in a very easy way modifing just one line in the Batch file.
#echo off
setlocal EnableDelayedExpansion
rem Define the list of variable names
set variables=JOB USER TEMPLATE ASSETROOT SHAREADDR SHARENAME SHAREDRIVE SHAREUSER SHAREPASS
rem Convert the list into an array of variable names
set i=0
for %%a in (%variables%) do (
set /A i+=1
set variable[!i!]=%%a
)
set numVariables=%i%
:: Read all the arguments for this batch script from external text file
rem Version 1: Single line of text, tokens delimited with comma
set i=0
for /F "delims=" %%a in (%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg) do (
for %%b in (%%a) do (
set /A i+=1
for %%i in (!i!) do set !variable[%%i]!=%%b
)
)
rem Version 2: Values of the variables on separate lines
set i=0
for /F "delims=" %%a in (%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg) do (
set /A i+=1
for %%i in (!i!) do set !variable[%%i]!=%%a
)
rem Display values of all variables
for %%i in (1,1,%numVariables%) do (
for %%v in (!variable[%%i]!) do echo %%v = !%%v!
)
In the first version, the line of the file is read in %%a replaceable parameter and then processed in a for command this way:
for %%b in (%%a) do (
For example:
for %%b in (apples,oranges,bananas,grapes,strawberries) do (
Because standard Batch delimiters are space, comma, semicolon and equal-signs, the values in the list are processed one by one in the for (with NO /F option). This method allows to easily separate a list of values in individual tokens in a regular for command, but works only with the indicated delimiters.

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