findstr for filename in win7 batch file - batch-file

I'm kind of struggling with the following search.
I need to look for files which are misplaced in wrong folders. I have the following testing structure (in reality it is hudreds of folders):
C:\test2\John\John_phone.txt
C:\test2\Mary\John_address.txt
C:\test2\Mary\Mary_address.txt
C:\test2\Mary\Mary_phone.txt
C:\test2\Mary\Peter_address.txt
The files John_address.txt and Peter_address.txt are misplaced in Mary's folder. I want to check Mary's folder for any misplaced files and list them in a separate log file. So for the example above the log would contain the names (paths) of the two misplaced files, The deciding identifier is the person's name. I have this piece of code:
#echo off
cls
set /p name="Specify the name: "
::forfiles /p "%CD%\%name%" /s /m *.* /c "cmd /c echo #path">>log.txt
forfiles /p "%CD%\%name%" /s /m "| findstr /i /v "\*%name%*"" /c "cmd /c echo #path">>log.txt
pause
The commented line for forfiles works (lists all files in the folder), so I have an issue with findstr: ERROR: Files of type "| findstr /i /v *Mary*" not found.
The /v switch with findstr should find all files that do not contain the specified name, but obviously I'm doing something wrong while using it as input for forfiles.
I don't want to use the dir command since it lists additional information and I need to integrate the output into larger log file (I need to get only the path of the misplaced file).
Any help is appreciated.
Thanks.
Edit: Would it be easier to write the code if the correct file name would be fixed like this?
All_data_%NAME%_new.txt
The stuff before and after the name would be fixed and this format of the file name would be the only correct option, so anything else would have to be reported.

For a simple solution
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=c:\test2"
( for /d %%z in ("%rootFolder%\*"
) do for %%y in ("%%~fz\*"
) do for /f "tokens=1 delims=_" %%a in ("%%~ny"
) do if /i not "%%~nxz"=="%%a" echo %%~fy
) > log.txt
This will iterate the files under each of the folders testing if their name starts with the same string that the folder name.
edited the original proposed solution does not work as intended, so, removed
edited - as the name of the file has not a fixed format, and the name of the folder can be in any place, this can be used
#echo off
setlocal enableextensions disabledelayedexpansion
set "rootFolder=c:\test2"
rem create a temporary file to hold the patterns to match against the list
rem of files to determine if it is correctly placed
set "patterns=%temp%\%~nx0.%random%.tmp"
> "%patterns%" (
for /d %%a in ("%rootFolder%\*") do echo(\\%%~nxa\\[^^\\]*%%~nxa[^^\\]*
)
rem Get the list of files, and filter to only get those that do not match
rem the generated patterns
dir /s /b /a-d "%rootFolder%\*" ^
| findstr /r /i /c:"%rootFolder:\=\\%\\[^\\]*\\." ^
| findstr /r /i /e /v /g:"%patterns%" ^
> log.txt
rem Patterns file is no longer needed
del "%patterns%" >nul 2>nul

this should help provided that comparison is case sensitive
for /f "delims=.'_\ tokens=2,3,*" %%a in ('forfiles /s /m *.txt /c "cmd /c echo #relpath"') do if NOT "%%a"=="%%b" #echo "%%a\%%b_%%c

Related

Batch count all files but exclude those in a specific folder

So I'm going to count files in a directory including all subfolders and get a output as a number of how many files it found within the directory. The problem is I want to exclude all the folders that has the name error. Those files within that folder I do not want to be counted.
Simply...
for /r "\\server\share\folderA" %%G in (*.*) do (
set /A count=count + 1
)
echo %count%
Under folderA there are plenty of subfolders that I'm counting, but also the "error" folders that I do not want to count.
So I'm trying the following...
Create a temp file called exclude.txt and type error to that file
if not exist "c:\temp" mkdir "c:\temp" 2>nul
if not exist c:\temp\exclude mkdir c:\temp\exclude 2>nul
echo error> %excludefolder%\exclude.txt
Now I want to combine this somehow. Basically do something like this...
for /r "\\server\share\folderA" %%G in (*.*) EXCLUDE: c:\temp\exclude\exclude.txt do (
set /A count=count + 1
)
But I'm aware this will not work and I'm not sure how to work it out. Does anyone know? Thanks!
Use DIR /S /B /A-D to iterate all files. The output includes the full path to each file.
Pipe that result to FINDSTR /L /I /V "\\error\\ to filter out paths that contain \error\. This will also exclude any folders within an error folder. The search could be modified to exclude only 'error' but include children of 'error'.
Pipe that result to FIND /C /V "" to count the number of files (lines).
dir /s /b /a-d | findstr /liv "\\error\\" | find /c /v ""
The above will simply display the count.
If you want to capture the count in a variable, then use FOR /F to parse the output of the above command. Unquoted poison characters like | must be escaped when used in FOR /F.
#echo off
for /f %%N in ('dir /s /b /a-d^|findstr /liv "\\error\\"^|find /c /v ""') do set count=%%N
echo count=%count%
You can exclude from count the folder containing the string "error" :
#echo off
set count=0
for /r "\\server\share\folderA" %%a in (*.*) do (
echo %%~pa | find /i "error" || set /A count+=1
)
echo %count%
It's a good way if you sure that you just have ONE Error folder. If you have another folder containing the string "error" it will be excluded too from count.

Handling File-Path Spaces in Batch Parameters

I am writing a Win 7 batch script for copying files from various source paths to a single location. The full path names of the files being copied are listed in a text file.
The following script works when the source paths do not include spaces. I can handle spaces if path names are included into the script as constants with a combination of quotations and %~1. How do I emulate this combination for paths being passed as parameters?
Transfer2.bat:
set SOURCELIST=c:\Temp\List1.txt
set DEST=c:\Temp\To
for /f %%A in (%SOURCELIST%) do (forfiles /p %%~dpA /s /m %%~nxA /c "cmd /c copy /y #path %DEST%\#file" 2>>log.txt)
for /f %b in (log.txt) do (echo.%~b)>>log.txt`
del log.txt
List1.txt:
C:\temp\From\Test_This Space.txt
C:\temp\From\Test.txt
Results:
Transfer is successful for C:\temp\From\Test.txt.
Log returns ERROR: Files of type "Test_This" not found. for C:\temp\From\Test_This Space.txt.
Is forfiles command required for your script? If not, I think this is good enough:
#echo off
set SOURCELIST=C:\Temp\List1.txt
set DEST=C:\Temp\To
for /f "delims=" %%A in (%SOURCELIST%) do (
copy /y "%%~fA" "%DEST%\%%~nxA" >>Log.txt 2>&1
)
type Log.txt
del /q Log.txt
pause
exit /b

Search for a string in a txt file under multiple folders

To put simply I am a temp IT for (Blank) motor company. I am trying to build a batch file that will search Progresslog.txt for a string. this string will be a user name like awilson. Thing is there is 1 progresslog.txt for each computer I have backed up under the folder names HMC(insert s/n) I need to search each progresslog for the string but can't figure out what I'm doing. This is what I have so far.
for /d /r ".\" %%a in (*) do if /i "%%~nxa"=="progresslog.txt" set "folderpath=%%a" & echo "%folderpath%"
for /f %%f in ('dir /b %folderpath%') do echo %%f & findstr /m "%Input%" progresslog.txt
if %errorlevel%==0 (
echo Found String!
) else goto A
It is a lot easier
findstr /s /l /m /c:"awilson" progresslog.txt
Just search in subdirectories (/s) the literal indicated (/l /c:"...") in files named progresslog.txt and output only the name of files found (/m)

Exclude multiple folders with Dir command

I had search thru the forum with excluding multiple files while using DIR command. But didn't find what i really needed. Some are even with PHP or VBS, really don't know how they works.
What I'm trying to do is *DIR*ing all profile folders and also excluding certain default folders, this is a part of showing what and how many users are having profiles on that computer.
I will explain a bit more because i may not fully be understood what my needs are.
If i use the DIR without findstr.
DIR /A:d /B "F:\Documents and Settings"
Output:
Administrator
All Users
Default User
LocalService
userprofile1
NetworkService
userprofile2
...
userprofileN
But my actual needs are:
userprofile1
userprofile2
...
userprofileN
I also got this far with my script now.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 ECHO Your OS does not support enable extensions
DIR /A:d /B "F:\Documents and Settings" | findstr /v "Admin" | findstr /v "Default" | findstr /v "LocalService" | findstr /v "NetworkService"
EXIT
My above script actually works but is fixed and may not be pretty coded.
I would ask about is it possible to use a For loop to shorten the long findstr pipes and set a variable that contains the folder names to exclude ?
I prefer to use a variable instead of a text files that contains folders to exclude.
I came up with below but it duplicates the ouput:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 ECHO Your OS does not support enable extensions
SET xUser="Admin" "Default" "hi_I_will_be_future_added"
FOR %%A IN (!Xuser!) DO (
DIR /A:d /B "F:\Documents and Settings" | findstr /v %%A
)
Thank you to this great forum and for all that may had helped both me and others.
#echo off
setlocal EnableDelayedExpansion
set exclude=/Administrator/All Users/Default User/LocalService/NetworkService/
for /F "delims=" %%a in ('DIR /A:d /B "F:\Documents and Settings"') do (
if "!exclude:/%%~Na/=!" equ "%exclude%" echo %%a
)
If you want to show the user name only (with no "F:\Documents and Settings" path), use echo %%~Na
Splitted in several lines for better reading, but, of course, it can be in a single line
#echo off
dir /ad /b "c:\Documents And Settings" ^
| findstr /l /i /x /v ^
/c:"Administrator" ^
/c:"All Users" ^
/c:"Default User" ^
/c:"LocalService" ^
/c:"NetworkService"
Or, instead of passing all the strings as /c:"..." arguments, you can generate a file with all the strings to exclude and use the /g:filename switch of findstr
F:\>dir /AD /B "c:\documents and settings"| FINDSTR /V "All Default Local Networ
k"
Admin
Administrator
F:\>

batch file - counting number of files in folder and storing in a variable

I am very new to this. Please help me
I was trying to write a batch file program to count number of files in a folder and assign that to a variable and display it to verify that it has been stored
please help me with the syntax,
thank you in advance
-VK
I'm going to assume you do not want to count hidden or system files.
There are many ways to do this. All of the methods that I will show involve some form of the FOR command. There are many variations of the FOR command that look almost the same, but they behave very differently. It can be confusing for a beginner.
You can get help by typing HELP FOR or FOR /? from the command line. But that help is a bit cryptic if you are not used to reading it.
1) The DIR command lists the number of files in the directory. You can pipe the results of DIR to FIND to get the relevant line and then use FOR /F to parse the desired value from the line. The problem with this technique is the string you search for has to change depending on the language used by the operating system.
#echo off
for /f %%A in ('dir ^| find "File(s)"') do set cnt=%%A
echo File count = %cnt%
2) You can use DIR /B /A-D-H-S to list the non-hidden/non-system files without other info, pipe the result to FIND to count the number of files, and use FOR /F to read the result.
#echo off
for /f %%A in ('dir /a-d-s-h /b ^| find /v /c ""') do set cnt=%%A
echo File count = %cnt%
3) You can use a simple FOR to enumerate all the files and SET /A to increment a counter for each file found.
#echo off
set cnt=0
for %%A in (*) do set /a cnt+=1
echo File count = %cnt%
#echo off
setlocal enableextensions
set count=0
for %%x in (*.txt) do set /a count+=1
echo %count%
endlocal
pause
This is the best.... your variable is: %count%
NOTE: you can change (*.txt) to any other file extension to count other files.....
The mugume david answer fails on an empty folder; Count is 1 instead of a 0 when looking for a pattern rather than all files. For example *.xml
This works for me:
attrib.exe /s ./*.xml | find /v "File not found - " | find /c /v ""
This might be a bit faster:
dir /A:-D /B *.* 2>nul | find /c /v ""
`/A:-D` - filters out only non directory items (files)
`/B` - prints only file names (no need a full path request)
`*.*` - can filters out specific file names (currently - all)
`2>nul` - suppresses all error lines output to does not count them
To build for statement you should know some details at first.
for /F %%i in ('dir /A:-D /B *.* 2^>nul ^| find /c /v ""') do set "COUNT=%%i"
The example above would work, but if you want to copy paste it into another for-expression - might not.
The for /F ... expression by default has ; character as EOL character and space+tabulation characters as line separators.
If you use a file path as input in for-expression, then you can override these characters:
for /F "eol= delims=" %%i in (";My file path") do echo.Value: %%i
Where the end of eol= might not visible here. It is just a file path invalid not printable character, in this case - code 04. In most consoles and editors (except stackoverflow itself) you can type it as:
press ALT
type 04 from numeric keypad
release ALT
Another issue avoid here is always reset variable you want to use before the for-expression in case if for-expression is not executed:
set FILE=undefined
for /F %%i in (";My file path") do set "FILE=%%i"
echo.FILE=%FILE%
The fastest code for counting files with ANY attributes in folder %FOLDER% and its subfolders is the following. The code is for script in a command script (batch) file.
#for /f %%a in ('2^>nul dir "%FOLDER%" /a-d/b/-o/-p/s^|find /v /c ""') do set n=%%a
#echo Total files: %n%.
Change into the directory and;
attrib.exe /s ./*.* |find /c /v ""
EDIT
I presumed that would be simple to discover. use
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "batchfile.bat";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
I run this and the variable output was holding this
D:\VSS\USSD V3.0\WTU.USSD\USSDConsole\bin\Debug>attrib.exe /s ./*.* | find /c /v "" 13
where 13 is the file count. It should solve the issue
for /F "tokens=1" %a in ('dir ^| findstr "File(s)"') do echo %a
Result:
C:\MyDir> for /F "tokens=1" %a in ('dir ^| findstr "File(s)"') do #set FILE_COUNT=%a
C:\MyDir> echo %FILE_COUNT%
4 // <== There's your answer
FOR /f "delims=" %%i IN ('attrib.exe ./*.* ^| find /v "File not found - " ^| find /c /v ""') DO SET myVar=%%i
ECHO %myVar%
This is based on the (much) earlier post that points out that the count would be wrong for an empty directory if you use DIR rather than attrib.exe.
For anyone else who got stuck on the syntax for putting the command in a FOR loop, enclose the command in single quotes (assuming it doesn't contain them) and escape pipes with ^.
I have used a temporary file to do this in the past, like this below.
DIR /B *.DAT | FIND.EXE /C /V "" > COUNT.TXT
FOR /F "tokens=1" %%f IN (COUNT.TXT) DO (
IF NOT %%f==6 SET _MSG=File count is %%f, and 6 were expected. & DEL COUNT.TXT & ECHO #### ERROR - FILE COUNT WAS %%f AND 6 WERE EXPECTED. #### >> %_LOGFILE% & GOTO SENDMAIL
)
With a for loop:
FOR /F %i IN ('dir /b /a-d "%cd%" ^| find /v /c "?"') DO set /a count=%i
echo %count%
Without/avoiding for loop:
(dir /b /a-d ^| find /v /c "?") | (set /p myVar=& cmd /c exit /b %myVar%)
set count=%errorlevel%
echo %count%
Tested in Win 10 cmd
Solution
Requires enabling Windows Subsystems For Linux
Ensure directoryToCount is set to the respective directory
SET directoryToCount=C:\Users\
dir %directoryToCount% > contentsOfDir.txt
echo cat contentsOfDir.txt ^| grep File > countFiles.sh
sh countFiles.sh
del countFiles.sh
del contentsOfDir.txt
Explanation
In both bash and batch environments, the output of a command can be redirected to a file using the > operator.
For example, echo hello world > myFile.txt will produce a file named myFile.txt with hello world as its text.
In a bash environment, one can cat the contents of a File and grep a particular line from the file containing a specified pattern.
For example, cat myFile.txt | grep hello will return lines containing hello
If Windows Subsystems for Linux is enabled, then one can execute sh from a Command Prompt to access a linux-like environment.
Therefore, we can solve this by doing the following
Use dir to acquire a list of files in the directory, as well as the number of files
Redirect the output of dir to a file (perhaps named contentsOfDir.txt).
Create a .sh file to grep for File from contentsOfDir.txt
Call the .sh file from command prompt to invoke the grep
Delete the .sh file
Delete contentsOfDir.txt

Resources