assigning a piped command to the variable batch - batch-file

I'm having trouble assigning a command that counts the number of times a file in a directory appears to a variable.
I found that I should do this - (^ |) but when I do it and echo the variable, nothing is displayed, and there should be a number of occurrences.
My code:
#echo off
setlocal enableextensions
for /f "tokens=*" %%i in ('dir /b C:\Users\AD10FC\IdeaProjects\collateral\db-resources\release | findstr /B "!first%!-" | find /c /v ""') do set VAR=%%i
echo %VAR%

There is no need to use findstr.exe in your code to filter the leading strings, because you can filter those directly in Dir:
#Echo Off
SetLocal EnableExtensions
Set "first=LeadingString"
For /F "EOL=? Delims=" %%G In ('"Dir /B /A:-D "%UserProfile%\IdeaProjects\collateral\db-resources\release\%first%-*" | "%SystemRoot%\System32\find.exe" /V /C """') Do Set "VAR=%%G"
Echo(%VAR%
Pause
Also for the specific task you're performing, you may find the following works better for you:
#Echo Off
SetLocal EnableExtensions
Set "first=LeadingString"
For /F %%G In ('""%SystemRoot%\System32\xcopy.exe" "%UserProfile%\IdeaProjects\collateral\db-resources\release\%first%-*" . /LQH"') Do Set "VAR=%%G"
Echo(%VAR%
Pause

Related

Find a string into each file of a folder with for loop

I try to find a string "blabla" inside a file. If I find the string I replace it with "bloblo", if not do nothing. And I want to do this operation for all the files that I have in a folder.
When I apply the script on one file, it works well. When I use a for loop it doesn't work. it does not enter inside the for loop
Here is my script:
set "Var1=blabla"
set "Var2=bloblo"
FOR %%i IN (C:\Users\UserName\Desktop\TEST\*.txt) DO (
find /c "%Var1%" %%i
if %errorlevel% equ 1 goto notfound
call PathFile\FUNCTION_REPLACE.cmd %Var1% %Var2% %%i
:notfound
)
I use a script "Function_replace" to replace the values, here is the script:
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%2"
Set "File=%3"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
I used to use directly the call of my replace function for each files of my folder. But it takes a long time to go inside each file. That's why I want to check before going inside each file, if the string exists or not (by using find /c).
Can you spot where is the issue coming from?
Based upon your latest edit, here's an example which sends only the files containing the string to be replaced, to the sub-function:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%~2"
For /F Delims^=^ EOL^= %%A In ('FindStr /LIMP "%search%" *.*')Do Call :Sub "%%A"
GoTo :EOF
:Sub
Set "File=%~1"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
Please note that the FindStr command uses only example options, whilst the /M option is important to this solution you should check the output from FindStr /? to determine which of the others you would consider the most appropriate.
Why not simply list all files that has the string and exclude the files that don't? That seems like a more obvious plan to me:
#echo off
set "search=blabla"
for /f "delims=" %%i in ('findstr /m %search% "%USERPROFILE%\Desktop\TEST\*.txt"') do (
echo found "%search%" in "%%~fi"
)
If you want to still show files that does not contain the path, then #stephan already posted a comment on how to, no need for me to repeat.

Count folders with names ending )x

I have a batch file which totals the number of directories:
for /d %%a in (*) do set /a count+=1
Now I need to total the directory names ending with the string )x, e.g. Mona Lisa (1986)x
I have tried unsuccessfully with:
for /d %%a in (")x") do set /a count+=1
You can let the find command count the items filtered by the dir command:
dir /B /A:D "*)x" | find /C /V ""
Prepend or append 2> nul to the dir part to suppress error messages in case no such directories exist.
To capture the resulting value and store it in a variable, use a for /F loop:
for /F %%C in ('2^> nul dir /B /A:D "*)x" ^| find /C /V ""') do set "COUNT=%%C"
echo %COUNT%
for /d %%d in (*^)x) do set /a count+=1
You may first want to check that it finds them correctly:
for /d %%d in (*^)x) do echo "%%~d"
Just an alternative, (the difference being that this doesn't ignore some directories, such as hidden ones):
For /F %%A In ('Dir /AD "*)x" 2^>Nul') Do Set "count=%%A"
You should really precede this with Set "count="

findstr /v removing space and dote not working

I have the below batch-file:
cd /d "T:\R\YOU"
for /r T:\R\YOU %%i in (.) do echo %%~nxi>>D:\MultiThreading\ReadFile.txt
cd /d D:\MultiThreading
rem I want to remove dots and spaces for the file content
findstr /v "." ReadFile.pbd >> 11.txt
findstr /v " " 11.pbd >> 12.txt
pause
I am getting the correct output from read file, however the output of 12.txt is empty, what I am doing wrong?
This is the output of ReadFile.txt file:
YOU
YOU 14.1.33333
YOU 14.1.44444
YOU 14.1.55555
YOU 14.1.44444
I want such output (I want to remove the first line):
YOU14133333
YOU14144444
YOU14155555
YOU14144444
The following code snippet read the file ReadFile.txt skipping the first line, removes spaces and dots from every line, and outputs the result into a file called ReturnFile.txt:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
> "ReturnFile.txt" (
for /F "usebackq skip=1 delims=" %%L in ("ReadFile.txt") do (
set "LINE=%%L"
setlocal EnableDelayedExpansion
set "LINE=!LINE: =!"
set "LINE=!LINE:.=!"
echo(!LINE!
endlocal
)
)
endlocal
exit /B
#Echo off
For /f "usebackq Tokens=1-10 delims=. " %%A in ("ReadFile.txt"
) Do If "%%B" Neq "" Echo:%%A%%B%%C%%D%%E%%F%%G%%H%%%I%%J
A bit primitive and rather short for answer.

Assign the result of a command to a variable (batch file)

I want to store the result of a command in a variable in a for loop in a batch script. I want to loop through a series of .sql files, count how many lines each file consists of and sum up the line counts.
Here is my attempt so far:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a <- THIS PRINTS THE FILE NAME
#set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
echo %t% <- I WANT TO PRINT THE LINE COUNT FOR THE FILE
#set /a count+=%t% <- INCREASE THE COUNTER
)
echo %count% <- PRINT TOTAL LINE COUNT
When I run
findstr /r /n "^" *.sql | find /C ":"
in a command window it works, and I know I could use that for the end objective, but this question is about the variable assignment.
Where is my mistake? The variable t is assigned the value 0 all the time.
UPDATE: (Still not working)
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a
for /L %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set /a count+=%%b
)
)
echo !count!
For anyone interested reading this later, here is the final (working version):
#ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a count=0
SET /a t=0
for /f %%a in ('dir /b *.sql') do (
#echo %%a
for /f %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set t=%%b
)
ECHO !t!
#SET /a count+=!t!
)
ECHO "Total:" !count!
#set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
doesn't work. It sets the variable t to the string findstr /r /n "^" %%a and filters the Output of the set command (which Outputs nothing) with | find /C ":", which Counts exactly Zero colons in nothing.
The best way of doing it, is:
for /f %%x in ('findstr /r /n "^" %%a ^| find /C ":"') do set t=%%x
Edit I was so focussed on repairing your code, that I didn't really realize, that you just want to count all lines of all *.SQL files. That's quite easy. No need for delayed expansion:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /n /v ""') do set /a count+=1
echo %count%
2>nul prevents type to print the file names to the screen.
Edit2
my solution with 203 files, 47763 lines in total needs about 24 seconds. Aschipfl's edit2 solution about seven milliseconds. Impressive... find /c must have a really efficient method to count the lines.
My slightly changed code to use this capability:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /c /n /v ""') do set /a count+=%%a
echo %count%
which also needs about 7ms. No big surprise, as it's basically the same code as Aschipfl's - just formatted differently.
There is no need to use findstr /N /R "^" to precede each line with line number and : and count the number of lines containing : afterwards.
To count the number of lines a text file contains, you only need to redirect it into find /C /V "", like this:
< "\path\to\file.txt" find /C /V ""
To use this within your for loop, you could do this:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set /A COUNT=0
set /A T=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
setlocal DisableDelayedExpansion
echo(%%~A
for /F %%B in ('^< "%%~A" find /C /V ""') do (
endlocal
set /A T=%%B
)
echo(!T!
set /A COUNT+=T
)
echo Total: %COUNT%
endlocal
exit /B
The toggling of delayed expansion is done to avoid trouble with exclamation marks ! in any of the *.sql file names, which would be ignored otherwise and the error message The system cannot find the file specified. would appear. Delayed expansion is only required because of the (debug) line echo(!T!; if you remove that, you can disable delayed expansion for the entire script.
Edit #1:
Here is a compacted variant of the above script, without any temporary variable T and with delayed expansion disabled:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
for /F %%B in ('^< "%%~A" find /C /V ""') do (
echo(%%~A: %%B
set /A COUNT+=%%B
)
)
echo TOTAL: %COUNT%
endlocal
exit /B
And here is a script that uses a single for /F loop to retrieve the number of lines, which lets find search for the *.sql files like find /C /V "" "*.sql", then takes its output that looks like ---------- file.sql: 5 for instance, splits off the count after : and sums up all of them. This approach needs delayed expansion again:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('find /C /V "" "*.sql"') do (
set "LINE=%%~A"
echo(%%~A
setlocal EnableDelayedExpansion
set /A T=!LINE:*: =!
for /F "delims=" %%B in ("!T!") do (endlocal & set /A COUNT+=%%B)
)
echo TOTAL: %COUNT%
endlocal
exit /B
Yes, there is a second for /F loop nested as well, but this is required for transferring the value of T over the endlocal barrier.
Edit #2:
Here is probably the best solution for determining the total number of lines over multiple files. This lets type output every line of all the *.sql files, which are then counted by find. Therefore the for /F loop iterates once only, so the overall performance of this script is quite great:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "delims=" %%A in ('
2^>nul type "*.sql" ^| find /C /V ""
') do (
set /A COUNT+=%%A
)
echo TOTAL: %COUNT%
endlocal
exit /B

Batch file to output last line of findstr

I am trying to find a list of machines in files in folders, and print out the last line of the output only.
#echo off
for /f %%a in (computers.txt) do findstr /xs "%%a" unhealthy.txt
pause
The computers.txt file has a list of 300 machines.
I want that to output only the last line of each instance it finds.
Right now the command displays and outputs all instances of the computer name, not just the tail end. I've tried to use "tail for Windows" but am getting errors as well.
Current output:
2013\10-Oct\28\unhealthy.txt:WIN57505
2013\10-Oct\29\unhealthy.txt:WIN57505
2013\10-Oct\30\unhealthy.txt:WIN57505
2013\10-Oct\31\unhealthy.txt:WIN57505
2013\11-Nov\1\unhealthy.txt:WIN57505
2013\11-Nov\4\unhealthy.txt:WIN57505
2013\11-Nov\5\unhealthy.txt:WIN57505
2013\11-Nov\6\unhealthy.txt:WIN57505
I only want:
2013\11-Nov\6\unhealthy.txt:WIN57505
#echo off
setlocal enableextensions disabledelayedexpansion
for /f %%a in (computers.txt) do (
set "line="
for /f "tokens=*" %%b in ('findstr /xs "%%a" *') do set "line=%%b"
setlocal enabledelayedexpansion
echo(!line!
endlocal
)
pause
endlocal
setLocal enableDelayedExpansion
for /f %%a in (computers.txt) do for /f "tokens=*" %%A in ('findstr /xs "%%a"') do set lastFound=%%A
echo !lastFound!

Resources