'comparing filenames with .bat and writing missing entries into .txt
i want to compare some files in a folder and then write missing ones into a text file.
i've got a folder
c:\sessions\
with files in it. those files are looking like:
Blabla-1111-FOO
Blabla-1111-BAR1
Bleble-2222-FOO
Bleble-2222-BAR1
Bleble-2222-BAR2
Bleble-2222-BAR3
Bleble-2222-BAR4
Blublu-5678-FOO
Blublu-5678-BAR1
Blublu-5678-BAR2
Blublu-5678-BAR3
Blublu-5678-BAR4
Blublu-5678-BAR5
Bleble-6666-FOO
Bloblo-7777-FOO
Bloblo-8888-FOO
Bloblo-9999-FOO
i need a .bat file which writes down all files ending with -FOO where no matching -BAR exists into a noBARs.txt. So in this case the noBARs.txt should look like this:
Bleble-6666-FOO
Bloblo-7777-FOO
Bloblo-8888-FOO
Bloblo-9999-FOO
There can be multiple -BAR files that belong to one -FOO file. Thanks in advance guys.
Solution 1:[1]
You could try the following:
@echo off
setlocal enabledelayedexpansion
set "source=c:\sessions"
set "output=noBARs.txt"
set "find=*foo"
set "repl=bar*"
1>"%output%" (
for %%e in ("%source%\%find%") do (
set "file=%%e"
if not exist "!file:~0,-3!%repl%" (
echo %%~ne
)
)
)
This will iterate through all the files that contain *foo
within their filename. Then it replaces the last 3 characters of the filename with bar*
and checks for the existence of the file. If the corresponding bar
file doesn't exist it will write the original filename to the output file noBARs.txt
.
I've added an alternative version of the script based on the last comment of dEEkAy in which he states that files ending with FOO
followed by a numerical constant should be tested as well. I'm still quite uncertain what the exact intention of dEEkAy is but I'm assuming that the file names *FOO*
should be handled the same as *FOO
.
The following input:
Blabla-1111-FOO
Blabla-1111-BAR1
Bleble-2222-FOO
Bleble-2222-BAR1
Bleble-2222-BAR5
Blublu-3333-FOO6
Blublu-3333-BAR1
Blublu-5678-FOO
Blublu-5678-FOO1
Blublu-5678-BAR2
Blublu-5678-BAR4
Bleble-6666-FOO
Bloblo-7777-FOO5
Bloblo-7777-BAR8
Bloblo-9999-FOO
Blublu-9999-FOO9
Bloblo-!^^!-FOO
Will produce the following output:
Bleble-6666-FOO
Bloblo-!^^!-FOO
Bloblo-9999-FOO
Blublu-9999-FOO9
The alternative version of the script is also more robust than the original. It should now be capable of handling file names and paths that contain exclamation marks and carets appropriately. Unfortunately, it does come with a cost. Due to the call
command which will be executed for each iteration of the for-loop, the script has become a lot slower. Perhaps someone with more batch-file scripting experience can come up with a better solution.
@echo off
setlocal disabledelayedexpansion
set "source=c:\sessions"
set "output=noBARs.txt"
set "find=foo"
set "repl=bar"
1>"%output%" (
for %%e in ("%source%\*%find%*") do (
set "path=%%~dpe"
set "file=%%~ne"
setlocal enabledelayedexpansion
call :ReplaceEndOfString file match "%find%" "%repl%"
if not exist "!path!!match!*" (
echo !file!
)
endlocal
)
)
exit /b
:ReplaceEndOfString (__in *source, __out *dest, __in find, __in repl) {
set "temp=!%1:*%~3=%~3!"
set "%2=!%1:%temp%=%~4!"
exit /b
}
Keep in mind that "%source%\*%find%*"
will match any file that contains %find%
within its file name, whereas "%source%\*%find%?"
only matches file names that end with %find%
including one optional character that could be anything.
I just happened to need some code similar to this and decided to take another look. The main bottleneck of the code seems to be the invocation of the call
command. While I don't see a way around this (other than using macros), the execution time of the call
command can be greatly improved (with a factor of 2, roughly).
Calling a function by its label seems to be a lot slower than calling the set
command. I'm not entirely sure but I can remember something about calling labels being slow due to requiring a rescan of the entire script file. Carets and exclamation marks within file names also appear to remain intact because the delayed expansion phase seems to occur before the set
command is called.
@echo off
setlocal DisableDelayedExpansion
set "source=c:\sessions"
set "output=nobars.txt"
set "find=foo"
set "repl=bar"
1>"%output%" (
for %%e in ("%source%\*%find%*") do (
set "path=%%~dpe"
set "file=%%~ne"
setlocal EnableDelayedExpansion
set "end=!file:*%find%=%find%!"
call set "match=%%file:!end!=%repl%%%"
if not exist "!path!!match!*" (
echo !file!
)
endlocal
)
)
exit /b
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |