How to find particular contents in list of files - windows

Please can someone tell how to find particular pattern in list of files.
I use the command:
dir *.txt /b /s >> C:\Users\Amrendra\Downloads\NIT_Testing\fileList.txt
In fileList.txt I have a list of files.
Now I want to find a certain pattern say abc in all the files listed.
So I want each line containing that pattern to be written into a new file.
Please suggest as I am completely new to batch command.
Thanks

I'm not sure if I got you completely right. You've echoed the names of all .txt files from some folder into one text file. Now you want to check it line by line for filenames containing some substring in the file name. Is that correct? If it is, here is the solution:
#ECHO OFF
SET targetFile=C:\Some\Path\SomeTextFile.txt
SET sourceFile=C:\Some\Path\Source.txt
SETLOCAL EnableDelayedExpansion
TYPE NUL>%targetFile%
FOR /F "tokens=*" %%L IN (sourceFile) DO (
SET templine=%%L
SET templine=!templine:abc=!
IF NOT !templine!==%%L (
ECHO %%L>>%targetFile%
)
)
Let's take a look on how it works: first we put the path to the file containing the file names into the variable %sourceFile% and the path to the target file into the variable %targetFile%. We need EnableDelayedExpansion to be able to work with changing variables inside the FOR-loop. TYPE NUL>%targetFile% simply clears the target file in case there are some entries from former runs.
The main work is done inside the FOR-loop. We read the source file line by line and want to check if the line contains the substring we are looking for. To do this we first store the line (%%L) in a temporary variable. Then we replace any occurrences of the search string with an empty string, means we simply remove abc from the temporary string. Finally we compare our modified temporary string with the original one. If they are equal we can be sure that the serch string abc was not in the original string. The other way around, if the strings differ, the substring was in the original string. So in the second case we do ECHO %%L>>%targetFile% which means we write the whole file name containing the search substring into our target file. Et voilĂ , we're done!
EDIT: As you want to search all listed files for the substring, here the new code:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET sourceFile=C:\Users\Amrendra\Downloads\NIT_Testing\fileList.txt
SET targetFile=C:\Users\Amrendra\Downloads\NIT_Testing\newList.txt
SET searchString=abc
TYPE NUL>%targetFile%
FOR /F "tokens=*" %%L IN (%sourceFile%) DO (
FINDSTR %searchString% "%%L">NUL
IF !ERRORLEVEL!==0 ECHO %%L>>%targetFile%
)
Here we are using findstr to check if a text file contains the string we are searching. As findstr usually would output the line which contains the searched string (which we don't want) we simply mute the command using >NUL. What we actually need is the ERRORLEVEL! If the string was found in a file findstr will set ERRORLEVEL to 0 or to 1 otherwise. So the only thing we have to do is to check if !ERRORLEVEL!==0.

Related

Trying to make a menu in a windows command prompt

I have a batch file that gets run by the user typing:
usercompile filename
usercompile is a batch file that does this:
copy /y %1.txt lib\incoming_file.txt
and then starts the compiler:
compiler.exe
The compiler has the "incoming_file" name hard-coded into linked source (this can't be chaged), so the current method is simply to copy the user file in and rename it to the known name and run the compiler.
I'd like to present the user with a list of files that are generated when a batch file is run, then the batch file would copy the selected file in, rename it (just like is done now).
So it would look like this:
Please choose a file to compile:
1) matthews_build
2) marks_build
3) lukes_build
and then the user would type 1 or 2 or 3 (in this case) and press enter. The batch file would copy that file to the known file name and launch the compiler. The one good thing is that the files that need to be listed all have a unique extension (.jal).
Any ideas?
I changed my approach and consider my previous answer a bad practice: re-listing the files with a second dir command unnecessarily reads the disk again, not to mention the rare but possible case if a file is added/removed between the 2 dir's and makes the whole thing unreliable.
Based on this brilliant solution I did a possible implementation with dynamic array:
#echo off
set /a counter=0
setlocal enabledelayedexpansion
FOR /f "delims=|" %%i IN ('dir /b /on "yourpath*.jal"') DO (
set /a counter+=1
rem echo !counter!^) %%~ni
set FileList[!counter!]=%%~ni & rem This is an array element, a dinamically created variable
)
rem Iterate through variables:
FOR /l %%i IN (1,1,!counter!) DO (
echo %%i^) !FileList[%%i]!
)
set /p option="Choose an option: "
echo !FileList[%option%]!
endlocal
This makes the file list available for any number of following commands.
One possible solution is to list all .jal files and give them an option number, store the result, and based on user input, look up the file based on the option number. As I know no way of storing such a result in memory (no array/hash table data type), only in a file, if a file can not be used, then the listing should be repeated in a deterministic way so that if we re-assign the option numbers, we get the same result. We can do it ensuring alphabetical ordering.
Here is one implementation:
BLOCK 1
setlocal enabledelayedexpansion
FOR /f "delims=|" %%i IN ('dir /b /on "yourpath\*.jal"') DO (
set /a counter+=1
echo !counter!^) %%~ni
)
endlocal
The nested dir command ensures alphabetical ordering (reference.)
A remark why I put a pipe (|) as a delimiter: if you don't define a delimiter, the default space will be used. If your file name contains space then it would be truncated. So I picked a character that is not valid in file names ensuring the whole file name is returned.
Now if you get a number from the user by this:
set /p option=Choose your option:
after this command (evaluating and possibly re-requesting the input) to do a lookup for the file you can repeat BLOCK 1 but replace the echo line with examining the option like this:
if !counter! == %option%
and put those commands in the if block to do whatever you want to do with the file (for debugging, put back the echo command).

Batch file locating duplicate patterns in filename then process

Ok, i've been working on a batch file for some time now, and im just stuck on the last bit.
What im trying to accomplish is to loop through a directory, create a variable which stores the filename of each file in the directory without the extension. Then for each file in the first loop, loop through a different directory and try to find any filename in the second loop that has the same name as stored in the variable, and then just output some simple text.
So for instance lets say in the first directory there is a filename called imafile-yehyeh.png, the variable will save imafile-yehyeh, then it will loop through all the files in the second directory, and output a message for each filename that has that pattern in it, so if a file in the second directory is called imafile-yehyeh_01.mp4 or imafile-yehyeh-newtitle.jpg, they would match the pattern and a message would output.
My script is looping and i am able to echo out all the variables, the files exist as i have created them exactly as shown above, but its not echoing out the filename is set for deletion line.
Any help would be greatly appreciated. my code is as follows;
#echo off
set "parent_folder=C:\Users\Testing\script"
set "dupe_folder=DUPEFOLDER"
set "kill_folder=1 SCANNED\thumb"
setlocal enableDelayedExpansion
for %%X in ("%parent_folder%\%dupe_folder%\*") do (
set dupe_pattern=%%~nX
for %%F in ("%parent_folder%\%kill_folder%\*") do (
echo %%~nF | FIND "%dupe_pattern%" 1>NUL && (
echo %%~F is set for deletion.
)
)
)
endlocal
Thanks to #Squashman the answer was to remove the set dupe_pattern.... line
and then change the FIND command to the following;
FIND "%%~nX"
Apart from needlessly setting a variable, as already pointed out, you are also making the script inefficient. For every file in the dupe_folder you are Echoing every file name in the kill_folder and piping that into a Find command looking for matches.
Here's a simpler way of doing it, (it matches file names which begin with the same string followed by a dot, as opposed to any file name containing the string anywhere).
#Echo Off
Set "parent_folder=C:\Users\Testing\script"
Set "dupe_folder=DUPEFOLDER"
Set "kill_folder=1 SCANNED\thumb"
CD /D "%parent_folder%" 2>Nul || Exit /B
For %%A In ("%kill_folder%\*") Do If Exist "%dupe_folder%\%%~nA.*" (
Echo %%A is set for deletion.)

Parsing every file in submap recursively to output folder whilst maintaining relativity

I'm using the following batch code to convert all files in a certain directory if the target file doesn't already exist however I'm stuck at getting this to run through every submap and file within that (and keep the output relative with that submap)
So I currently use this:
for %%f in (input/textures/*.*) do ( IF NOT EXIST "ouput/textures/%%~nf.dds" (
"bin/ThempImageParser.exe" "input/textures/%%f" "ouput/textures/%%~nf.dds"
)
)
This works perfectly for a single folder (as was intended), it takes all the files in that specific folder, and passes them as arguments to my executable, which then outputs the file on the path of the second argument.
However this also contains a flaw (this is an additional problem though..) as it does not work if the output -folder- does not exist, so if possible I'd also want it to create the folder if need be.
I've found some batch documentation (I really don't have much experience with Batch) showing me a command called FORFILES and the /R parameter, however I couldn't adjust this so it'd keep the relative paths for the output too, it'd require string manipulation and I have no clue on how to do that.
So the result I'm after is something like this, it takes any file deeper than "input/textures/ for example:
input/textures/some/very/deep/submap/why/does/it/go/on/myfile.anyExtension
it should then take that file (and relative path) and basically change "input" with "output" and replace the file extension with .dds like this:
ouput/textures/some/very/deep/submap/why/does/it/go/on/myfile.dds
and pass those two strings to my executable.
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir\wherever\something"
FOR /f "delims=" %%a IN ('xcopy /y /L /s "%sourcedir%\*"') DO (
SET "destfile=%%a"
SET "destfile=!destfile:*%sourcedir%=%destdir%!"
IF /i "%%a" neq "!destfile!" (
FOR %%m IN ("!destfile!") DO IF NOT EXIST "%%~dpm%%~na.dds" (
ECHO MD "%%~dpm"
ECHO "bin\ThempImageParser.exe" "%%a" "%%~dpm%%~na.dds"
)
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
First, perform an xcopy with the /L option to list-only the individual fullnames of files that would be copied by the xcopy.
Assign each name found from %%a to destfile, then remove all characters before the source-directoryname from that filename, and replace that string with the destination directoryname.
This will yield the destination name for the file (with the original extension). The only exception will be the very last output line, which is a count-of-files report. Since this line will not contain the source directoryname, the replacement will not take place, so %%a will be the same as !destfile! - so we eliminate that.
Now assign the destination filename to a metavariable so we can select its various parts, and if the filename made from the destination drive and pathname, the name part of the original file and .dds does not exist, then make the destination directoryname and execute the imageparser, providing the desired output filename.
Note that these last two are ECHOed instead of being executed for testing purposes. Remove the ECHOes to actually perform the command.
Note that / is a switch-indicator, \ is a directory-separator.
Note that MD will report an error if the directory already exists. Append 2>nul to the end of the md command to suppress that error message.

Output the entire line based on matching string on the command line

I have an input file that looks like:
application database variable value
+-------------------+-------------------+-------------------+-------------------
O_PrTot Rptg ClosedMonthsFY13 Jan:Dec
O_PrTot Rptg OMNICORE_Year FY14
O_PrTot Rptg ClosedMonthsFY14 Jan:Oct
I need to find value for ClosedMonthsFY14 which is Jan:Oct and place this output
into .txt file.
Thanks
Based on your title "Ouput the entire line based on matching string" and your comment "and place this output into .txt file", this should work. We make use of the FINDSTR command, which according to the TechNet article I linked, "searches for patterns of text in files using regular expressions." We don't particularly need a regular expression in this case, but it will work nonetheless:
FINDSTR /I "ClosedMonthsFY14" C:\path\to\input.txt > C:\path\to\output.txt
The switch /I means make the search case-insensitive.
#ECHO OFF
SETLOCAL
FOR /f "tokens=3,4" %%a IN (q27307586.txt) DO IF /i "%%a"=="ClosedMonthsFY14" SET "outstring=%%b"
ECHO %outstring%
FOR /f "delims=" %%a IN ('findstr /i "ClosedMonthsFY14" q27307586.txt') DO SET "outstring2=%%a"
ECHO %outstring2:~61%
GOTO :EOF
I used a file named q27307586.txt containing your data for my testing.
There are two different methods here. The first method relies on the assumption that each column contains exactly one string which does not include separators like spaces or commas.
The second method uses the column-position; 61 characters in the selected line are skipped and the remainder assigned to the variable.
To actually output the variable to a file, simply append >"filename" to the appropriate echo line
Note that the second method will retain the trailing spaces on the line, which may or may not be appropriate for your purpose.
The /i switch in each case makes the string-match case-insensitive.
(Your question header states "the entire line" but your narrative says you need to find the value)

Batch file for loop string replacement

I have a batch file that take a directory path as a parameter.
In that file folder, there are any number of .ai.pdf or .pdf files that I need to convert to jpg's. The conversion is not my issue (I am using imageMagick) , but lopping off the full extension is.
I need to be able to either take off the full .ai.pdf (7 characters) or .pdf (4 characters) from the file name and replace it with .jpg I cannot use just ~n in the for loop because it will not take off the .ai in an instance with there is an .ai.pdf (results in file name.ai where I need just the file name)
There are quite a few posts on StackOverFlow about this
StackOverFlow Example
but no matter what I attempt to try, I get an error when truncating the appropriate amount of extension off of the file name.
Here is my code. This is the first major batch file I have ever created, so I am open to anything, other than installing more programs to do the work.
The thing that kills me, is I had this working and in the shuffle from one server to another and a week of vacation, the working code got....misplaced.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set dir1=%1
echo recieved !dir1!
for /R %dir1% %%a in (*.pdf) DO (
echo file found !a!
set b=th_%%~nxa
if x%b:ai.pdf=%==x%b% set b=%%~dpa!b:~0,-7!
if not x%b:ai.pdf=%==x%b% set b=%%~dpa!b:~0,-4!
REM convert -density 64 "%%a" +matte -resize 15%% "!b!.jpg"
#echo !b! converted
)
ENDLOCAL
the file tells me that %~dpa!b:~0,-7! is an invalid substitution
Any ideas? Thanks for the help!
A few things first:
!a! and %%a are two different variables.
if x%b:ai.pdf=%==x%b% does not mean what you think it does. That will only be true when %b% does NOT contain .ai.pdf.
Again, if not x%b:ai.pdf=%==x%b% does not mean what you think. This is true when %b% DOES contain .ai.pdf.
There is no need to do any verification and cutting, just search and replace. ( That is what the %y:x=z% notation does, in this example it replaces every x within %y% with a z.) Let search and replace do the verification. It will only replace what matches the search. That will speed up the your batch file.
Lastly, since you are inside a () code block you will need to use the delayed Expansion turned on with your setlocal statement. This is because everything inside a code block is treated as if it were on a single line. That means that if you change a variable inside a code block, you will not be able to see the new value using the % notation. Instead you need to replace the %'s with !'s. For instance...
setlocal enableDelayedExpansion
set x=Hello
(
set x=Goodbye
echo I don't know why you say "!x!", I say "%x%".
)
...will give you the old Beatles lyric...
I don't know why you say "Goodbye", I say "Hello".
Anyway, on to your answer:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set dir1=%1
echo recieved !dir1!
for /R %dir1% %%a in (*.pdf) DO (
:: Adding a colon to the end of the filename allows the extension to be ID'd
: without explicitly looking at it with an IF statement, while simultaneously
:: avoiding similar looking character groupings inside the filename.
set b=th_%%~nxa:
:: No need to check for case, the substitution will do that for you.
set b=!b:.ai.pdf:=.jpg!
set b=!b:.pdf:=.jpg!
REM convert -density 64 "%%a" +matte -resize 15%% "!b!"
echo %%a converted into !b!
)
ENDLOCAL
The drawback is that both the files...
X.ai.pdf
X.pdf
...will be translated into th_X.jpg, creating the possibility of duplicate filenames for two different files.
But that's intrinsic to your concept of treating both types of filenames the same. If you don't have a method for avoiding this sort of duplication it might not be a bad idea to leave the .ai on the file, thereby creating two files: th_X.jpg and th_X.ai.jpg, eliminating the possibility of duplicate filenames.
Hm... would this work for you:
for /R %F in (*.pdf) do #for %G in ("%~nF") do #echo %~nxF ==^> %~nG.jpg
(as executed directly from cmd, if run from batch, replace % with %%).
This has a peculiar effect of changing the case of a file to case of a directory if there exists one with the same name as base name of your file (file.pdf will become FILE.jpg if you happen to have a subdirectory called FILE), but that's it (I think).
This also assumes your base names differ (so no file.ai.pdf and file.pdf in same directory)

Resources