Batch: Filter filename - batch-file

I have lot file that need to filter before move to other folder.
The filter condition:
[PEQ]*_[+-][1-9][0-9]_[P-R][0-9]_*[._][0-9]*
Example of filename:
P101_+19_R0_3.0_QA.txt
I try to apply the filter in batch script but nothing happen.
Am i correctly defined the filter?
My script:
SET _ext1=txt
SETLOCAL ENABLEDELAYEDEXPANSION
for %%f in (%_source%\[PEQ]*_[+-][1-9][0-9]_[P-R][0-9]_*[._][0-9]*.%_ext1%) do (
echo %%f >> %LOG%
SET _path=%%~df%%~pf
echo !_path! >> %LOG%
SET _filename=%%~nf
echo !_filename! >> %LOG%
echo. >> %LOG%
echo Processing !_filename! >> %LOG%
IF EXIST !_path!!_filename!*.%_ext1% (
copy /Y "!_path!!_filename!*.%_ext1%" "%_target%" >> %LOG%
)
)
ENDLOCAL

I hope you understand the difference between a wildcard * matching any number of any chars and the RegEx * which means any number (also zero) of the previous match. Together with the RE . any char .* will resemble the wildcard *
#Echo off & SETLOCAL ENABLEDELAYEDEXPANSION
SET _ext1=txt
for /f "delims=" %%f in (
'dir /B "%_source%\*_*_*_*.%_ext1%" ^| Findstr /i "%_source%\[PEQ]*_[+-][1-9][0-9]_[P-R][0-9]_.*[._][0-9]*.%_ext1%" '
) do (
echo %%f >> %LOG%
SET _path=%%~df%%~pf
echo !_path! >> %LOG%
SET _filename=%%~nf
echo !_filename! >> %LOG%
echo. >> %LOG%
echo Processing !_filename! >> %LOG%
IF EXIST !_path!!_filename!*.%_ext1% (
copy /Y "!_path!!_filename!*.%_ext1%" "%_target%" >> %LOG%
)
)
ENDLOCAL
You should first test the line with the dir and findstr in an open cmd window,
then without the escaping ^ and surrounding '
dir /B "%_source%\*_*_*_*.%_ext1%"
If this fits as a first selection add
dir /B "%_source%\*_*_*_*.%_ext1%" | Findstr /i "%_source%\[PEQ]*_[+-][1-9][0-9]_[P-R][0-9]_.*[._][0-9]*.%_ext1%"
And vary your RegEx until it does what you want.
Remember that findstr RegEx capabilities are quite limited.

Related

Findstr second column and make new batch

As you can see, the batch file makes a VBS script and it should make another batch file, but it doesn't, since findstr /R "^ECHO" "%~sf0" >> "temp.bat"
copies the code including the echo. I want to copy the line after ECHO and place them in a temporary file.
Here is my code
#echo off
echo This is batch
:::wscript.echo "This VBScript"
:::wscript.echo "Today is " & day(date) & "-" & month(date) & "-" & year(date)
findstr "^:::" "%~sf0">temp.vbs & cscript //nologo temp.vbs & del temp.vbs
goto b
ECHO #echo off
ECHO setlocal enabledelayedexpansion
ECHO set SCRIPT_INSTANCES=20
ECHO :: Create a temporary file if one doesn't already exist
ECHO if not exist script_count.txt >script_count.txt echo(%SCRIPT_INSTANCES%
ECHO :: Read in the value of the config file
ECHO set /p script_counter=<script_count.txt
ECHO :: If the value of script_counter is greater than 1, decrement it and start again
ECHO if %script_counter% gtr 1 (
ECHO set /a script_counter-=1
ECHO >script_count.txt echo(!script_counter!
ECHO
ECHO start "" cmd /c "%~0"
ECHO ) else (
ECHO del script_count.txt
ECHO )
ECHO color a
ECHO :a
ECHO tree C:/
ECHO goto a)
:b
findstr /R "^ECHO" "%~sf0" >> "temp.bat"
pause
exit
You can strip off the leading echo by using the space as a delimiter.
So change this line.
findstr /R "^ECHO" "%~sf0" >> "temp.bat"
To this
FOR /F "TOKENS=1* DELIMS= " %%G IN ('findstr /R "^ECHO" "%~sf0"') DO echo %%H >>"temp.bat"
One drawback to this code is that it will strip all the indentation of your code.

How do I combine files in order

I have/found a windows batch script that will combine csv files from all sub-directories. It works great in Windows 10 but when I run the script in Windows 7, all the files are out of order. How do I force the order in which to combine the csv files?
echo #off
for /r %%i in (*.csv) do (
if not %%~nxi == output.csv (
echo %%~nxi >> output.csv
echo %%i
echo %%~nxi
type "%%i" >> output.csv
echo. >> output.csv
echo. >> output.csv
)
)
Just a little change to your code will do the job:
#echo off
FOR /F "usebackq delims=" %%i IN (`dir /s /b /O:N *.csv`) do (
if not "%%~nxi" == "output.csv" (
echo %%~nxi >> output.csv
echo %%i
echo %%~nxi
type "%%i" >> output.csv
echo. >> output.csv
echo. >> output.csv
)
)
Point is to use another command's out -- use dir to control the sorting order.
/b for clean output by dir
/O for ordering, N -- name.
check FOR /? and dir /? for more details.
PS: you may wanna use:
echo %%~dpnxi >> output.csv
instead of line 4's echo %%~nxi >> output.csv , to show full path of each file in your output.csv.
This is just a slight modification to POW's answer that should give you better performance. This technique keeps the file open for writing. When you use the append multiple times, it is opening and closing the output file. So the file pointer has to be reset every time it outputs to the file.
#echo off
(FOR /F "usebackq delims=" %%i IN (`dir /s /b /O:N *.csv`) do (
echo %%~nxi
echo %%i >con
type "%%i"
echo.
echo.
)
)>output.tmp
rename output.tmp output.csv
Here is another possible solution:
#echo off
for /R %%A IN (*.csv) do (
if not "%%~nxA"=="output.csv" (
(echo %%~fA && type "%%~fA" && echo. && echo.)>>output.csv
echo Processed: %%A
echo %%~nxA
)
)
with much less code.
Using /R option with for to loop through subfolders in %cd%.
We want to parse ALL csv files so, we specify it in parenthesis with (*.csv).
Then, we check if csv file currently processed is output.csv.
If not, then we append full path of the csv ("%%~fA") file, its content (type "...") and two newlines (echo.) to output.csv. This condition is not really required, but added to be on-topic with the question. Also, if you don't want to append full path to output.csv, but filename and extension only just replace %%~fA with %%~nxA.
After that, we echo current file processed and its filename and extension.
If file currently processed is output.csv, then we repeat the loop.
Now, output.csv has the contents of all csv files in all subdirectories.
So, now open a new cmd and type the following commands. Read the output carefully:
for /?
if /?
echo /?
type /?
Some suggestions for further reading:
https://ss64.com/nt/for_cmd.html
https://ss64.com/nt/for_r.html
https://ss64.com/nt/syntax-redirection.html
What does "&&" in this batch file?
Thanks to all of you for your help. After reading all the responses, I realized that I could get around the windows sorting problem by sorting into a second file and then reading it from there.
dir /b /s /O:N *.csv | sort > file.txt
for /f %%A IN (file.txt) do (
if not %%~nxA == output.csv (
echo %%~dpnxA
echo %%~nxA >> output.csv
type %%A >> output.csv
echo. >> output.csv
echo. >> output.csv
)
)
Again, thank you for all your help.

Deleting Empty Directories in Batch with Exceptions

I recently started creating some small batch files, as I think that Batch in itself is interesting, but also because it helps automate some things that I do on a regular basis.
The script that I'm working on is a program that deletes all directories in a folder (As of now put in as the %UserProfile%), and allows all entires in an Exception file to be ignored. I don't want Exact Paths, I wanted it so that if the exception was present anywhere in the folders path, then it needs to be excluded.
Here's what I have (Keep in mind I'm not very good):
#ECHO OFF
CD %UserProfile%
SET /A Violation=0
SET "ExceptionFile=%*"
SETLOCAL ENABLEDELAYEDEXPANSION
SHIFT
ECHO Starting...
ECHO Scan started at %TIME% > "%UserProfile%\Log.txt"
FOR /f "usebackq delims=" %%D in (`"dir /ad/b/s | sort /R"`) DO CALL :DIREXPANDER "%%D"
ECHO Scan Finished at %TIME% >> "%UserProfile%\Log.txt"
GOTO:EOF
:DIREXPANDER
SET /A Violation=0
SET Directory=%1
ECHO %Directory%
FOR /F %%X IN (%ExceptionFile%) DO (
SET "Exception=%%X"
ECHO %Directory% Compared to %Directory:!Exception!=% >> "%UserProfile%\Test.txt"
If NOT %Directory%==%Directory:!Exception!=% (
ECHO EXCEPTION: %Directory% Violates !Exception! >> "%UserProfile%\Log.txt"
REM SET /A Violation=1
)
)
IF %Violation%==0 (
RMDIR %Directory% 2>NUL && ECHO DELETION: %Directory% >> "%UserProfile%\Log.txt"
)
GOTO:EOF
If I replace !Exception! With an actual String, it works just fine--but when using a variable it doesn't seem to work.
Thanks for any suggestions or issues that you notice!
Pretty sure you can write this without using the CALL to the Label.
#ECHO OFF
CD %UserProfile%
SET "ExceptionFile=%*"
SETLOCAL ENABLEDELAYEDEXPANSION
SHIFT
ECHO Starting...
ECHO Scan started at %TIME% > "%UserProfile%\Log.txt"
FOR /f "usebackq delims=" %%D in (`"dir /ad/b/s | sort /R"`) DO (
SET "Violation=0"
SET "Directory=%%D"
ECHO %%D
FOR /F %%X IN (%ExceptionFile%) DO (
ECHO %%D Compared to !Directory:%%X=! >> "%UserProfile%\Test.txt"
If NOT "%%D"=="!Directory:%%X=!" (
ECHO EXCEPTION: %%D Violates %%X >> "%UserProfile%\Log.txt"
SET "Violation=1"
)
)
IF "!Violation!"=="0" (
RMDIR "%%D" 2>NUL && ECHO DELETION: %%D >> "%UserProfile%\Log.txt"
)
)
ECHO Scan Finished at %TIME% >> "%UserProfile%\Log.txt"
This nested code was 5 seconds faster on my computer.

Recursive search by file list

I have a TXT file with a list of names like:
Test
Word
etc.
I need to search ( recursive, so also in subfolder ) if one of that name match with a file. This is my attempt:
#echo off
Set MyPath=C:\Folder
for /f %%i in (list.txt) do (
echo File with word %%i: >> result.txt
echo. >> result.txt
findstr /M /C:%%i /S "%MyPath%\*.*" >> result.txt
echo. >> result.txt
)
The result.txt i want is:
File with word test:
C:\Folder\test.exe
C:\Folder\my test.txt
C:\Folder\another test.doc
C:\Folder\tatest.bat
File with word Word:
C:\Folder\This is my word.exe
C:\Folder\CoolWord.txt
C:\Folder\hello word.bat
So how to improve that batch and make it recursive also for the subfolder of the initial dir?
Thanks
Test this: It will write result.txt with the results for each word.
#echo off
(
for /f "usebackq delims=" %%a in ("list.txt") do (
echo "File with word %%a:"
echo.
set "flag="
for /r "c:\folder" %%b in ("*%%a*") do (echo %%b&set flag=1)
if not defined flag echo No Matches
echo.
)
)>"result.txt"
dir /s /b C:\Folder\*.* >allfiles.txt
for /f %%i in (list.txt) do (
echo File with word %%i: >> result.txt
echo. >> result.txt
findstr /M /C:%%i /S "allfiles.txt" >> result.txt
echo. >> result.txt
)
#echo off
Set MyPath=C:\Folder
(for /f "delims=" %%i in (list.txt) do (
echo File with word %%i:
echo/
dir /B /S "%MyPath%\*%%i*"
echo/
)) > result.txt

Batch: Copy a list (txt) of files ignoring extension

I have the next batch file, but its matching by file name. This time the list I have is huge and has file names without extension, but can I ignore the extension and copy for example: filename.* to the destination folder?
This is the current script:
title Deploying Edithor
set src_folder=S:\ApliTelinver\Compilacion\Edithor 10.5\Pipe
set dst_folder=J:\alazarev\Objetos-Migracion-Pipe
set filelist=filelist-pipe.txt
echo Origen: %src_folder% >> "pipemigracion-!datetimef!.log"
echo Destino: %dst_folder% >> "pipemigracion-!datetimef!.log"
echo.
REM for /f %%i in (%filelist%) DO xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" > "%dd%.log"
for /f "delims=" %%i in (%filelist%) do (
xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" >> "pipemigracion-!datetimef!.log"
)
echo Success. >> "pipemigracion-!datetimef!.log"
echo.
echo Done - Check log pipemigracion-!datetimef!.log
echo.
pause
goto start
Here's how I've understood the question. The file list, filelist-pipe.txt, contains file names, and all of the names are without extensions.
If so, you only need to append .* to the source file path in the XCOPY command:
title Deploying Edithor
set src_folder=S:\ApliTelinver\Compilacion\Edithor 10.5\Pipe
set dst_folder=J:\alazarev\Objetos-Migracion-Pipe
set filelist=filelist-pipe.txt
echo Origen: %src_folder% >> "pipemigracion-!datetimef!.log"
echo Destino: %dst_folder% >> "pipemigracion-!datetimef!.log"
echo.
REM for /f %%i in (%filelist%) DO xcopy /S/E/U/Y "%src_folder%\%%i" "%dst_folder%" > "%dd%.log"
for /f "delims=" %%i in (%filelist%) do (
xcopy /S/E/U/Y "%src_folder%\%%i.*" "%dst_folder%" >> "pipemigracion-!datetimef!.log"
)
echo Success. >> "pipemigracion-!datetimef!.log"
echo.
echo Done - Check log pipemigracion-!datetimef!.log
echo.
pause
goto start
Please let me know if I'm still missing something.

Resources