findstr: [^inverse class] incorrect behaviour - findstr

I don't want findstr to display a string that contains 'btq' between - and -
For example: ghjgvyu-btq-jklli8j
So I've tried this command:
echo ghjgvyu-btq-jklli8j|findstr .*-[^btq]-.*
Not working at all... Does not display anything with or without ^
Then I tried:
echo ghjgvyu-btq-jklli8j|findstr "[^btq]"
Does the opposite: It always displays the string no matter if ^ is used.
It's only working correctly when I echo btq and nothing else:
echo btq|findstr "[^btq]"
But that's not what I want.

My solution would be to run findstr with /V, /C and /R parameter:
findstr /V /R /C:"-btq-"
/R is a parameter which enables searching with a regex. With parameter /C you specify a concrete string/regex which you are searching for in a line and with /V you search for lines which do not contain the match given in parameter /C.
So for example:
#echo off
echo 1 ghjgvyu-btq-jklli8j | findstr /V /R /C:"-btq-"
echo 2 ghjgvyu-bt-jklli8j | findstr /V /R /C:"-btq-"
echo 3 ghjgvyu-b-jklli8j | findstr /V /R /C:"-btq-"
echo 4 ghjgvyu-avc-jklli8j | findstr /V /R /C:"-btq-"
echo 5 abc | findstr /V /R /C:"-btq-"
gives me
2 ghjgvyu-bt-jklli8j
3 ghjgvyu-b-jklli8j
4 ghjgvyu-avc-jklli8j
5 abc
You see, the string ghjgvyu-btq-jklli8j which should not occur in the output does not occur there.

Related

Search for a string may containing spaces and special characters in the specific type of files in entire directory structure

I have following batch script to check the specific type of files, in entire directory structure from the current directory, if a string is found in those files or not:
#echo off
set RESULT_FILE="result.txt"
set /p STR="Enter the String to Find: "
pushd %~p0
type NUL > %RESULT_FILE%.tmp
for /f "delims=" %%a in ('dir /B /S *.phtml') do (
for /f "tokens=3 delims=:" %%c in ('find /i /c ".%STR:"=%." "%%a"') do (
for /f "tokens=*" %%f in ('find /i ".%STR:"=%." "%%a"') do if %%c neq 0 echo %%f
)
) >> "%RESULT_FILE%".tmp
move %RESULT_FILE%.tmp %RESULT_FILE% >nul 2>&1
:: Open the file
"%RESULT_FILE%"
popd
But my search string may contain spaces between multiple words and special characters too.
How can I modify the search string variable STR to allow spaces and special characters in the search string as literal?
Right now zero results are returned when the search string contains spaces and special characters.
The following should work. I remove the quotes before the for loop, but only the outer, how it works is explained here at ss64. To work with special characters like a carret (^) I enabled delayed expansion.
Further it won't work with prepending and appending . in the search string, I don't know why you've added it.
I've also added a /A-D so that the dir command will not list directory names.
#echo off
setlocal EnableDelayedExpansion
set RESULT_FILE="result.txt"
set /p STR="Enter the String to Find: "
:: Remove just outer quotes not quotes that are inside
set STR=###!STR!###
set STR=!STR:"###=!
set STR=!STR:###"=!
set STR=!STR:###=!
pushd %~p0
type NUL > %RESULT_FILE%.tmp
for /f "delims=" %%a in ('dir /B /S /A-D *.phtml') do (
for /f "tokens=3 delims=:" %%c in ('find /i /c "%STR%" "%%a"') do (
for /f "tokens=*" %%f in ('find /i "%STR%" "%%a"') do if %%c neq 0 echo %%f
)
) >> "%RESULT_FILE%".tmp
move %RESULT_FILE%.tmp %RESULT_FILE% >nul 2>&1
:: Open the file
"%RESULT_FILE%"
popd

Grep and run a Batch

Is it possible to grep a value then store it in a file via batch file??
Like for example,
grep "error 404" Mow*2015.txt | wc -l
grep "error 403" Mog*2015.txt | wc -l
Then I want it to put in a batch for it to generate another txt file or other extension.
set ARH = * grep for the 404 *
set ARG = * grep for the 403 *
ECHO %ARG% %ARH% >> admin.log
Is it possible to do so?
I suppose you have installed cygwin or Windows Services for UNIX.But you can use windows command only to achieve what you want:
for /f "delims=" %%# in (
'"%windir\system32\FIND.EXE%" "error 404" mow*2015.txt' ^| "%windir\system32\FIND.EXE%" /c /v /n ""
) do set "ARH=%%#"
for /f "delims=" %%# in (
'"%windir\system32\FIND.EXE%" "error 403" mow*2015.txt' ^| "%windir\system32\FIND.EXE%" /c /v /n ""
) do set "ARG=%%#"
ECHO %ARG% %ARH% >> admin.log

In a batch file, how do you verify part of a filename matches a given string?

I have a directory full of files that look like the following:
Codian1_OCT_14_2014_14_52_ccc145b1_WMV.asf
Codian1_OCT_14_2014_14_52_ccc145b1_ASF.asf
Codian1_OCT_13_2014_12_52_ccc145b1_WMV.asf
Codian1_OCT_13_2014_12_52_ccc145b1_ASF.asf
I'm trying to test if the file ends in either WMV.asf or ASF.asf. For some reason the following code doesn't work:
FOR %%i IN (*) DO (IF %%~i=="*WMV.asf" (echo %%~i IS wmv.asf) ELSE (echo %%~i isn't wmv.asf))
Any idea how to do this?
All comparisons should be case insensitive, since Windows doesn't care about case within file paths.
Option 1
#echo off
setlocal enableDelayedExpansion
for %%i in (*) do (
set "file=%%i"
if /i "!file:~-7!"=="wmv.asf" (echo %%i IS wmv.asf) else (echo %%i isn't wmv.asdf)
)
Option 2
for %%i in (*) do echo %%i|findstr /ile "wmv.asf" >nul && (echo %%i IS wmv.asf) || (echo %%i isn't wmv.asf)
A way :
#echo off
setlocal enabledelayedexpansion
FOR %%i IN (*) DO (
set $File=%%i
if /i !$File:~-7!==WMV.asf echo !$File! -^> WMV
if /i !$File:~-7!==ASF.asf echo !$File! -^> ASF)

Trim a text file via a batch file

I want to trim a text file from both top and bottom.
Say if the text file contain 90 lines. I want to delete top x lines and bottom y lines and update the file. (ie leave only the range x+1 to y-1.
Hence I to intend write a batch file and run it as follow.
trimmer.bat file1.txt 2 8
This code below has following limitations
(a) file open/amend twice
(b) Trims blank lines within the range (I do not wish to remove these lines)
Please help me to correct
#echo off
rem %1% file name %2%range begins %3%range ends
rem Step1: this code trims the bottom section
set /a bot_trim=%3
echo Removing...
for /f "skip=%bot_trim% delims=*" %%a in (%1) do (
echo %%a >>newfile.txt
) >nul
echo Lines removed, rebuilding file...
xcopy newfile.txt %1 /y >nul
echo File rebuilt, removing temporary files
del newfile.txt /f /q >nul
echo file bottom trimmed...
rem Step2: this code trims the Top section
set /a Top_trim=%2-1
echo Removing...
for /f "skip=%Top_trim% delims=*" %%a in (%1) do (
echo %%a >>newfile.txt
) >nul
echo Lines removed, rebuilding file...
xcopy newfile.txt %1 /y >nul
echo File rebuilt, removing temporary files
del newfile.txt /f /q >nul
echo file bottom trimmed...
echo file trim completed !!
pause
contents of file1.txt
aa
ff
ff
dd
dd
ee
ee
ee
#ECHO OFF
SETLOCAL
FOR /f "tokens=1-3 delims=:" %%a IN ('FIND /c /v "" %1') DO IF "%%c"=="" (SET /a endline=%%b-%3) ELSE (SET /a endline=%%c-%3)
ECHO %2 %endline%
(
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r "^" %1') DO (
IF %%a gtr %endline% GOTO done
IF %%a gtr %2 ECHO(%%b
)
)>newfile.txt
:done
GOTO :EOF
Designed to suit your original specification. No attempt to cater for spaces and batch-significant symbols in file/directorynames, but directorynames may be used if required.
Lines beginning : will be damaged.
Produces newfile.txt

Using findstr with regular expressions to search sections of a string

I have created code which loops through each line of files.txt and identifies if the file is car, boat or neither and stores this information into SendType.txt. This is accomplished by using the findstr command and searching through the list of boat.txt and car.txt. Essentially the way the code is designed, it will take the first line of files.txt and see if it can find the string in car.txt (if so car is output to SendType.txt) if not it will search for the string in boat.txt (if the string is found in boat.txt, boat is output to SendType.txt), and if the string is not found in either car.txt or boat.txt, then the text neither is output to SendType.txt
Right now the code searches for the entire string line. Each string is similar to 11111_2222-22_2010-09-09_10-24-20.zip (11111=ID, 2222-22=model, 2010-09-09=date, 10-24-20=transaction ID).
I would like to replace my current findstr line, which searches the entire line, to search for the entire string EXCEPT the date portion. I have attached my code below for reference along with some examples of the files being input. Thanks in advance!
#echo off
FOR /F %%a in (files.txt) do (
findstr %%a car.txt
if errorlevel 1 (
findstr %%a boat.txt
if errorlevel 1 (
echo neither >>SendType.txt
) else (
echo boat >>SendType.txt
)
) else (
echo car >>SendType.txt
)
)
car.txt
11111_2222-22_2010-09-09_10-24-20.zip
11112_2222-11_2011-11-09_10-24-25.zip
boat.txt
11122_1111-22_2012-04-09_11-29-56.zip
11144_3333-11_2011-12-22_06-29-66.zip
files.txt
11122_1111-22_2000-01-01_11-29-56.zip
11144_3333-11_2000-01-01_06-29-66.zip
11155_1212-12_2000-01-01_11-19-69.zip
11111_2222-22_2000-01-01_10-24-20.zip
11112_2222-11_2000-01-01_10-24-25.zip
12345_2233-12_2000-01-01_07-27-44.zip
DESIRED OUTPUT:
SendType.txt
boat
boat
neither
car
car
neither
UPDATE 10/15 3:00 PM
The current approach using dbenham's code and the parsing technique is as follows:
#echo off
>SendType.txt (
for /f "tokens=1,2,3,4 delims=_" %%a in (filenames.txt) do (
findstr /c:"%%a_%%b_%%d" sneakernet.txt >nul && (echo sneakernet) || (
findstr /c:"%%a_%%b_%%d" devmed.txt >nul && (echo devmed) || echo tanto
)
)
)
If the format of the IDs is fixed with two _ that precede the date, then the solution is easy: simply use FOR /F to parse the values.
I like to use && and || instead of testing ERRORLEVEL. Also, you don't need the output of FINDSTR, so you can redirect to nul. You should verify that the string matches from the begining of the line. Finally, you only need to redirect once, so you can overwrite instead of append - easier to test repeatedly because no need to delete before start.
#echo off
>SendType.txt (
for /f "tokens=1,2 delims=_" %%a in (files.txt) do (
findstr /bc:"%%a_%%b" car.txt >nul && (echo car) || (
findstr /bc:"%%a_%%b" boat.txt >nul && (echo boat) || echo neither
)
)
)
If the format (and possibly length) of the ID can vary, but the format (length) of the date portion is constant, then you can use a substring:
#echo off
setlocal enableDelayedExpansion
>SendType.txt (
for /f "delims=" %%a in (files.txt) do (
set "ln=%%a"
findstr /bc:"!ln:~0,-23!" car.txt >nul && (echo car) || (
findstr /bc:"!ln:~0,-23!" boat.txt >nul && (echo boat) || echo neither
)
)
)
If neither the ID nor date format is constant, then I would change the content of boat.txt and car.txt by stripping off the date portion. Then you can use the FINDSTR /G option. The /I option is needed because of a bug in FINDSTR.
car.txt
11111_2222-22
11112_2222-11
boat.txt
11122_1111-22
11144_3333-11
#echo off
setlocal enableDelayedExpansion
>SendType.txt (
for /f "delims=" %%a in (files.txt) do (
echo %%a|findstr /blig:car.txt >nul && (echo car) || (
echo %%a|findstr /blig:boat.txt >nul && (echo boat) || echo neither
)
)
)
Updated answer
Now that I understand the requirements, this should solve the problem. I've basically used a variation of the 1st code in my original answer, and I've switched to using a regular expression. The test could be made more stringent by substituting [0-9] for each . in the regex.
#echo off
>SendType.txt (
for /f "tokens=1,2,4 delims=_" %%a in (files.txt) do (
findstr /brc:"%%a_%%b_....-..-.._%%c" car.txt >nul && (echo car) || (
findstr /brc:"%%a_%%b_....-..-.._%%c" boat.txt >nul && (echo boat) || echo neither
)
)
)

Resources