Removing part of filename with batch - batch-file

I've tried to tweak a lot of the code provided to similar questions, but I don't think the solution is posted. My problem is that the part from where I want to remove the rest exists 2 times before the last!
What I have is a folder with:
number1-number2-number3 - some random text about the file.filetype
number1 will range from 01 to 99
number2 will range from 1-99999
number3 will range from 1-999 with the possibility of 2 decimals, separated from whole number by .
Example folder c:\temp\:
15-1592-1 - file 1.doc
15-1592-2 - this is file2.pdf
15-1592-3 - this cointains subfiles.html
15-1592-3.1 - sub1.jpg
15-1592-3.2 - sub2.pdf
What I need is a folder where everything after the end of number3 is removed from the filename, but also the file type unaltered.
Example:
15-1592-1.doc
15-1592-2.pdf
15-1592-3.html
15-1592-3.1.jpg
I understand this is quiet possible from reading all the answers combined.
What I lack is the knowledge to compile it all!

You want to delete everything after the first space (without the extension)
This is quite easy, if you use modifiers (see for /?):
#echo off
setlocal enabledelayedexpansion
for %%a in (??-*-*) do (
for /f "tokens=1 delims= " %%b in ("%%~na") do (
ECHO ren "%%a" "%%b%%~xa"
)
)

its' a little bit tricky to extract the decimal part (if present), but this should do the job (may need some token adjustment to fit your needs)
#echo off
setlocal enabledelayedexpansion
set "source_path=c:\temp\*"
for /f "tokens=1,* delims=." %%a in ('dir /b %source_path%') do (
set "ext=" & set "decimal="
for /f "tokens=1,* delims=." %%i in ("%%b") do (
if "%%j" neq "" (
set "ext=%%j"
for /f "tokens=1,* delims=- " %%d in ("%%i") do set "decimal=.%%d"
) else (
set "ext=%%i"
)
)
for /f "tokens=1-3,* delims=- " %%i in ("%%a") do (
rem replace echo with operation you need
echo %%i-%%j-%%k!decimal!.!ext!
)
)
endlocal

Related

Batch file: count duplicate ids and write them in column of csv

I am currently trying to automate the preprocessing process on a csv file via a batch file. I have the following table:
id;street;name;nrOfIds
4014001;T1;example1;0
4014002;B2;example2;0
4014003;B3;example3;0
4014004;L1;example4;0
4015001;M3;example5;0
4015002;B9;example6;0
4016001;T4;example7;0
4016002;L2;example8;0
4016003;L1;example9;0
The first row "id" holds the id of the entry which is made unique by the last 3 digts (for example 001, 002, 003, ...). The digits before the last three digits are not unique. As you can see in the result table, I want to count how often the first part of the ID (so the part before the last three digits) exists in the table and I want to write the sum into the third column named "nrOfIds". The result table then should look like this:
id;street;name;nrOfIds
4014001;T1;example1;4
4014002;B2;example2;4
4014003;B3;example3;4
4014004;L1;example4;4
4015001;M3;example5;2
4015002;B9;example6;2
4016001;T4;example7;3
4016002;L2;example8;3
4016003;L1;example9;3
For example, the part before the last three digits of the first line (4014) exists exactly 4 times in the whole table, so I write 4 in the "nrOfIds" column and so on.
The code used for this looks like this:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=1-3* delims=;" %%a in (%PREPROCESSING_INPUT_PATH%%INPUT_FILENAME%) do (
(echo %%a;%%b;%%c)> "%PREPROCESSING_INPUT_PATH%%OUTPUT_FILENAME%" & goto :file
)
:file
(for /F "skip=1 tokens=1-3* delims=;" %%a in (%PREPROCESSING_INPUT_PATH%%INPUT_FILENAME%) do (
REM count ids (like 4014, 4015, ... and write sum into "nrOfIds" column
)
) >> %PREPROCESSING_OUTPUT_PATH%%OUTPUT_FILENAME%
pause
Any suggestions on how to do this? Thank you very much in advance! Your help is greatly appreciated.
Pretty similar to the previous answer I posted, here we just use find /C to identify the number of occurrences of the last 3 digits of the ID:
#echo off
setlocal enabledelayedexpansion
set "infile=z:\folder31\testcsv.csv"
set "outfile=%PREPROCESSING_OUTPUT_PATH%testOutput.csv"
for /f "usebackq delims=" %%a in ("%infile%") do (
(echo %%a)>"%outfile%" & goto :file
)
:file
(for /f "skip=1 usebackq tokens=1-4*delims=;" %%a in ("%infile%") do (
set "match=%%a"
for /f %%i in ('findstr /B "!match:~0,-3!" "%infile%" ^| find /C "!match:~0,-3!"') do (
set /a _cnt=%%i
echo %%a;%%b;%%c;!_cnt!
)
)
)>>"%outfile%"
Debug version:
#echo off
setlocal enabledelayedexpansion
set "infile=%PREPROCESSING_INPUT_PATH%%INPUT_FILENAME%"
set "outfile=%PREPROCESSING_OUTPUT_PATH%%OUTPUT_FILENAME%"
for /f "usebackq delims=" %%a in ("%infile%") do (
(echo %%a) & goto :file
)
:file
(for /f "skip=1 usebackq tokens=1-4*delims=;" %%a in ("%infile%") do (
set "match=%%a"
for /f %%i in ('findstr /B "!match:~0,-3!" "%infile%" ^|find /C "!match:~0,-3!"') do (
set /a _cnt=%%i
echo %%a;%%b;%%c;!_cnt!
)
)
)
pause
This method is simple and run fast:
#echo off
setlocal enabledelayedexpansion
rem Count ids
for /F "skip=1 delims=;" %%a in (input.txt) do (
set "id=%%a"
set /A "count[!id:~0,-3!]+=1"
)
rem Update the file
set "header="
(for /F "tokens=1-4 delims=;" %%a in (input.txt) do (
if not defined header (
echo %%a;%%b;%%c;%%d
set "header=1"
) else (
set "id=%%a"
for /F %%i in ("!id:~0,-3!") do echo %%a;%%b;%%c;!count[%%~i]!
)
)) > output.txt
A method based on external commands, like findstr or find, is slower...

Locating keyword in .csv files

I am trying to create batch file that reads specific CSV documents from specific file, and extracts some lines that have specific number and print it out on the screen " the whole line !". The problem is I created the code but it wont work at all, whenever I tried it only prints the line numbers!?
The code:
#echo off
setlocal EnableDelayedExpansion
set "yourDir=C:\Users\Adminm\Desktop\test11\"
set "yourExt=csv"
set "keyword=44"
set /a count=0
set linenum=!count!
set c=0
pushd %yourDir%
for %%a in (*.%yourExt%) do (
for /f "usebackq tokens=3 delims=," %%b in (%yourDir%%%a) do (
set /a count = !count! + 1
if NOT %%b == %keyword% (
for /f "delims=" %%1 in ('type %yourDir%%%a') do (
set /a c+=1 && if "!c!" equ "%linenum%" echo %%1%
)
)
)
)
echo !count!
popd
endlocal
thanks in advance <3
for %%a in (*.%yourExt%) do (
for /f "usebackq delims=" %%L in ("%%a") do (
for /f "tokens=3 delims=," %%b in ("%%L") do (
if %%b == %keyword% echo %%L
)
)
)
Assuming what you want to do is scan each file for a target string in column3, then:
Since you have already changed to yourdir, there's no requirement to specify it in the scan-for-filenames for.
Your attempt to locate the required line is clumsy. All you need to do is assign each line in turn to a metavariable (%%L) and then use for/ to parse the metavariable. When the required data matches, simply echo the metavariable containing the entire line.
You've attempted to use %%1 as a metavariable. %n for n=0..9 refers to the parameter number supplied to the routine. The only officially defined metavariables for use here are %%a..%%z and %%A..%%Z (one of the very few places where batch is case-sensitive) - although some other symbols also work. Numerics will not work here.

Rename text files based on multiple strings in their contents

Firstly, there are a couple of similar questions on here to this (Rename file based on file Content batch file being the one I have tried to work an answer from - but I have no real clue what I'm doing), however I cannot find anything that meets my exact needs, and this is my first real foray into batch programming so the syntax is fairly new to me.
The question:
I have several hundred text files, with different names, where the header is formatted like so:
"Event Type : Full Histogram"
"Serial Number : xxxxxx"
"Version : V 10.60-8.17 "
"File Name : W133FA0Z.580H"
"Histogram Start Time : 12:39:08"
"Histogram Start Date : 2014-04-11"
I would like if possible to create a batch file to rename all the files in the folder to the format of:
StartDate StartTime
so for this example:
2014-04-11 12:39:08
My problems lie in the fact I'm not sure how to actually point it to where to find the string if it was for just one line (I've tried editing the answers in the question I posted above). And, futhermore, I have no idea how to add a second bit of code to find the StartTime string and then append that to the StartDate.
Thanks in advance,
Chris
Here is a very efficient method.
#echo off
pushd "pathToYourFolderContainingFilesToRename"
for /f "tokens=1,3 delims=:" %%A in (
'findstr /bc:^"\"Histogram Start Date :" *.txt'
) do for /f delims^=^"^ %%C in (
"%%B"
) do for /f tokens^=4-6^ delims^=^":^ %%D in (
'findstr /bc:^"\"Histogram Start Time :" "%%A"'
) do ren "%%A" "%%C %%D.%%E.%%F.txt"
popd
The 1st loop serves two purposes. It establishes file names that contain the start date string, as well as also returning the date string for each file.
The 2nd loop strips out spaces and quotes from the date string.
The 3rd loop parses out the start time from the file.
The 2nd and 3rd loops have very awkward syntax to enable including a quote in the list of delimiters. The 2nd loop sets DELIMS to a quote and a space. The 3rd set DELIMS to quote, colon, and a space.
Assuming you JUST have file formatted like in your description in the working directory :
#echo off&cls
setlocal EnableDelayedExpansion
for %%x in (*.txt) do (
set /a $sw=1
for /f "skip=4 tokens=2-4 delims=:" %%a in ('type "%%x"') do (
if !$sw! equ 1 set $Time=%%a-%%b-%%c
if !$sw! equ 2 (
set $Date=%%a
call:DoRen !$Time:~1,-1! !$Date:~1,-1! %%~nx%%~xx)
set /a $sw+=1
)
)
exit/b
:DoRen
echo ren "%3" "%2 %1"
If the output is OK you can remove the echo
The following will get the output you want, where the output will look like 2014-04-11 123908.
#echo off
set file=test.txt
for /f "delims=: tokens=2-4" %%a in ('find "Time" %file%') do set ftime=%%a%%b%%c
for /f "delims=: tokens=2" %%a in ('find "Date" %file%') do set fdate=%%a
echo %fdate:~1,-1% %ftime:~1,-1%
If all the files are in the same directory, then you can simply do this in a another for loop.
#echo off
setLocal enableDelayedExpansion
for /f %%f in ('dir C:\whatever\path\*.txt /B') do (
for /f "delims=: tokens=2-4" %%a in ('find "Time" %%a') do set ftime=%%a%%b%%c
for /f "delims=: tokens=2" %%a in ('find "Date" %%a') do set fdate=%%a
ren "%%~a" "!fdate:~1,-1! !ftime:~1,-1!.txt"
)
This will rename all text files in a specified directory the date and time in their contents. Note that this does not account for text files that do not have the date and time in their contents. You can (and probably should) add that as you see fit.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
DEL incorrectformat.log 2>nul
DEL alreadyprocessed.log 2>nul
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%\*.txt" ') DO (
SET keepprocessing=Y
SET "newname="
FOR /f "tokens=1-5delims=:" %%b IN (
'TYPE "%sourcedir%\%%a"^|findstr /n /r "$" ') DO IF DEFINED keepprocessing (
IF %%b==1 IF NOT "%%~c"=="Event Type " SET "keepprocessing="&>>incorrectformat.log ECHO %%a
IF %%b==5 SET newname=%%d%%e%%f
IF %%b==6 (
SET "keepprocessing="
SET "newname=%%d!newname!.txt"
SET "newname=!newname:"=!"
SET "newname=!newname:~1!"
IF "!newname!"=="%%a" (>>alreadyprocessed.log ECHO(%%a) ELSE (ECHO REN "%sourcedir%\%%a" "!newname!")
)
)
)
GOTO :EOF
Here's my version.
You'd need to set the value of sourcedir to your target directory.
A list of files not matching the specified format is produced as incorrectformat.log
A list of already-processed files is produced as alreadyprocessed.log
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO REN to REN to actually rename the files.

Stopping when a string has been found

Hello StackOverflow community!
I have a BATCH question that has been plaguing me for a few days now:
I am trying to do a sting comparison (sounds simple) but I am doing it in this manner:
I have two Folders: SESSIONS and TARGETS.
Each of these folders has a ordinary text files that have been named after a server: Server1.txt, Server2.txt, Server3.txt, etc. Both directories have files with exactly the same names. The file names are important only because after reading them, I will know where to allocate the information that is contained in that file. Example:
SESSIONS-->Server1.txt
Word_one
Word_two
Word_three
word_seven
TARGETS-->Server1.txt
Word_one
Word_two
Word_seven
This is the code that i am using to traverse the Sessions and Targets folders:
FOR %%a in (%ses_dir%*.txt) DO (
FOR /F "TOKENS=1 DELIMS= " %%c in (%%a) DO (
FOR %%f in (%targ_dir%*.txt) DO (
FOR /F "TOKENS=1 DELIMS= " %%i in (%%f) DO (
SET tmp_nam=%%~na
IF %%c EQU %%i ( ECHO This is Connected)
IF %%c NEQ %%i ( ECHO This is not Connected)
)
)
)
)
The above will print out all the sessions that are connected and all the sessions that are not connected. Essentially, this will output a LOT of redundant and useless information. I would like it to do the following:
Every time it finds a string from the first file in the second file, Stop right there, and move onto the next string in the first file.
If it does not find the string from the first file in the second file. Echo "String not found" or something along those lines.
I have tried to be as descriptive as I could. Let me know if you have any additional questions.
Thank you in advance!
This can be done with the built-in associative arrays of the Batch language:
#echo off &SETLOCAL
SET "sessionDir=SESSIONS"
SET "targetDir=TARGETS"
FOR %%a IN ("%sessionDir%\*.txt") DO (
IF NOT EXIST "%targetDir%\%%~nxa" (
ECHO "%%~nxa" NOT found IN "%targetDir%"
) ELSE (
FOR /f "usebackqdelims=" %%b IN ("%%~fa") DO SET "$%%b=1"
FOR /f "usebackqdelims=" %%b IN ("%targetDir%\%%~nxa") DO SET "#%%b=1"
FOR /f "delims=$=" %%x IN ('set "$"') DO IF NOT DEFINED #%%x ECHO "%%x" missing IN "%targetDir%\%%~nxa"
FOR /f "delims=#=" %%x IN ('set "#"') DO IF NOT DEFINED $%%x ECHO "%%x" missing IN "%%~fa"
)
)
Please note: the Word_ items can't have = signs, leading or trailing space.
FOR %%a in (%ses_dir%*.txt) DO (
FOR /F "TOKENS=1 DELIMS= " %%c in (%%a) DO (
SET "tmp_nam="
FOR /F "TOKENS=1 DELIMS= " %%i in (%targ_dir%%%~nxa) DO IF NOT DEFINED tmp_nam (
IF %%c EQU %%i SET tmp_nam=%%~na
)
if defined tmp_nam (echo %%c connected) else (echo %%c not connected)
)
)
This should, I believe, achieve your end.
%%a is set to each session's textfilename in turn.
%%c is set to each word from the textfile in %%a and tmp_nam is cleared
%%i is set to each word from the identical filename in the targets directory.
If a match is found, tmp_nam is set to something (it doesn't matter what, just not empty) The remainder of the comparisons to the remaining words in targets are skipped because tmp_nam is now defined.
Depending on whether a match was found or not, the word that matched + "(not) connected" is output. Could just as easily be %%a or both %%c and %%a if that floats your boat.
Now - if you mean that you want to say %%a (not) connected if ANY ONE word in the session is matched in targets, regardless,
FOR %%a in (%ses_dir%*.txt) DO (
SET "tmp_nam="
FOR /F "TOKENS=1 DELIMS= " %%c in (%%a) DO (
FOR /F "TOKENS=1 DELIMS= " %%i in (%targ_dir%%%~nxa) DO IF NOT DEFINED tmp_nam (
IF %%c EQU %%i SET tmp_nam=%%~na
)
)
if defined tmp_nam (echo %%a connected) else (echo %%a not connected)
)
which is simply moving the reporting out one level.

How to find a string and replace part of it using batch commands?

I have text file with lot of parameters with unique names. I need to find a parameter by its name and change the value of the parameter. The file looks something like this
ID Value Name
4450 2.0 / [var_pot] 'DCF_loc'
4451 100.0 / [var] 'DCF_t'
4452 0.1 / [var] 'DCF_dur'
4458 1000.0 / [var] 'CommtF_t_P1'
For e.g. I need to find the parameter 'DCF_t' in the file and replace its value from 100 to some other value say 10. Unfortunately in my case, only the names and values of the parameters are in my control. I am in need of a batch file to do the "find and replace" job.
Please help me out...Thanks in advance...
in case it is Windows, you need to
loop over all the lines of the file. try something like.. FOR /F %%a in (values.txt) DO echo %%a
skip the first header line. Try FOR /f "skip=1" %%a in (%1) do echo %%a
parse the contents of the line. Try FOR /f "skip=1 tokens=1-5" %%a in (%1) do echo %%b %%d
check the fourth item. Try
for /f "skip=1 tokens=1-5" %%a in (%1) do (
if /i .%%e.==.'DCF_t'. (
echo %%a 99.9 %%c %%d %%e
) else (
echo %%a %%b %%c %%d %%e
)
)
and you almost done, or at least in your way to the solution. See HELP FOR and HELP IF for more information.
This is a little bit cryptic for batch beginners. And there are many better languages to do this job.
But it can be done also with batch.
The key is to rewrite the file and modify the correct line.
set "otherValue=10"
setlocal EnableDelayedExpansion
(
For /f "tokens=1,2,*" %%a in (myFile.txt) do (
set "var=%%c"
if "!var!"=="!var:DCF_t=!" (
rem ** not found, echo the line
echo(%%a %%b !var!
) ELSE (
rem ** Found the line
echo(%%a %otherValue% !var!
)
)
) > outfile.txt
This assumes, that there are no exclamation marks in the text and that the lines are formatted always into three parts delimited by spaces or tabs.

Resources