Batch program script problem breaks with file names with spaces - batch-file

The following is a batch script that calls mp3splt (a program that splits mp3s http://mp3splt.sourceforge.net/mp3splt_page/home.php) into partitions of 5 mins long.
for /f %%a IN ('dir /b *.mp3') do call c:\PROGRA~1\mp3splt\mp3splt -t 5.0 -o output\#f+-+#n+-+#t %%a
It breaks when the mp3 files contain a space. Can anyone propose a workaround?

for %%a IN (*.mp3) do (
call c:\PROGRA~1\mp3splt\mp3splt -t 5.0 -o output\#f+-+#n+-+#t "%%a"
)
What others are saying here to quote the variable is doubtless correct. That's needed for it to work correctly. But it also is only half the solution.
Your problem here is that dir /b spits out lines of text, each one containing a single file name, like so:
foo bar.mp3
baz gak.mp3
track01.mp3
...
for /f on the other hand is made for reading files or something else (the dir output in this case) line by line ... but it also does tokenizing. That means it splits strings at configurable places into individual tokens.
By default, /F passes the first blank
separated token from each line of each
file. Blank lines are skipped. You
can override the default parsing
behavior by specifying the optional
"options" parameter. This is a quoted
string which contains one or more
keywords to specify different parsing
options. —help for
So you only get the part before the first space of the file name. You can work around that by using
for /f "delims=" in ...
to specify that tokenizing should be done with no delimiters, essentially giving you the complete line each time. But a better way is actually the one I outlined at the start to just use the regular for to iterate over the files. No surprises with spaces in file names there and it actually makes your intent a lot clearer.
I am regularly surprised why people tend to choose a convoluted and wrong solution over a simple, clear and correct one.

You can quote the variable containing the file name:
"%%a"

Related

How to output multiple lines from a FINDSTR to a variable

It's no surprise that the official documentation doesn't really help in the matter of understanding how does the command process the result of a command instead of a filelist neither why is it even called 'FOR'. Yes I already know Stack Overflow is full of similar question but apparently, since batch scripts are influenced by so many
"breaking" factors that, even as a non-batch experienced programmer, it is difficult not to get lost in the thousands exceptions and do-nots which may affect the result.
My objective, aside from learning from the best answer possible, is to formulate a generic enough question to represent the matter which is probably the most common task including the FINDSTR command:
THE QUESTION:
How do I get the output of a FINDSTR in a way that allows me to compute every result line one at the time
possibly INSIDE the loop?
The most 'generic' (batch bs-proof if you know what I mean) example I can make is the following:
Let's say this is secret_file.txt
some not interesting line
A very interesting line = "secret1";
some not interesting line
A very interesting line = "secret2";
some not interesting line
A very interesting line = "secret3";
some not interesting line
Now with the findstr command I can output every "secret" line like this:
findstr /R /C:"secret.\"" secret_file.txt
A very interesting line = "secret1";
A very interesting line = "secret2";
A very interesting line = "secret3";
But this result is just useless without further parsing right? I could have used ctrl-F over any text reader/editor
for this matter, anyway, let's say I now want to output every line ONE AT THE TIME so that I can compute it, for
example, saving every secret to a variable then using that variable somehow
(it doesn't really matter how, we can just echo it to keep things simple).
Now, everybody agrees on the fact that for this kind of task, a FOR loop is needed.
Quoting https://ss64.com/nt/for.html on the syntax, my script.bat should looks like this:
#echo off
FOR /F %%A IN ('findstr /R /C:"secret.\"" secret_file.txt') DO ECHO Batch script language is completely fine, good job Microsoft!
This just doesn't even give any output, can someone explain me why? My hypothesis was that the output from the findstr command
is in a non-compatible format with the FOR command, not like I could check or something since the source is closed and the
documentation doesn't even bother defining the word String.
I'm ready to provide any details and even edit the question to be more visible to the wanna be Microsoft-forsaken batch scripters out there.
Using "tokens=*" to strip off leading spaces this batch uses a counter to create a (pseudo) array secret[]
:: Q:\Test\2018\12\04\SO_53614102.cmd
#Echo off
set Cnt=0
FOR /F "tokens=*" %%A IN (
'findstr /R /C:"secret.\"" secret_file.txt'
) DO (
set /a Cnt+=1
call Set Secret[%%Cnt%%]=%%A
)
Set Secret[
Sample output:
> SO_53614102.cmd
Secret[1]=A very intersting line = "secret1";
Secret[2]=A very intersting line = "secret2";
Secret[3]=A very intersting line = "secret3";
As variables in a (code block) are expanded at parse time,
delayed expansion is requiered (here through a call and doubled %%)

How to compare the text lines from two files in batch

That is the identical content of my 2 txt files formatliste_droid.txt and formatliste_siegfried.txt. I want to know if all the lines till delimiter $:$ are identical 1-1, 2-2 and so on.
Z:\15_Testdateien\jhove_Script_fuer_MIX-Verzeichnisse\testfiles\BVBBV042064787\Files\E\images.jpg$;$fmt/43
Z:\15_Testdateien\jhove_Script_fuer_MIX-Verzeichnisse\testfiles\BVBBV042064787\Files\E\Van Schijndel House - English.mp4$;$fmt/199
Z:\15_Testdateien\jhove_Script_fuer_MIX-Verzeichnisse\testfiles\BVBBV042064787\Files\E\Van Schijndelhuis - Nederlands.mp4$;$fmt/199
That's my code:
#echo off
Setlocal EnableDelayedExpansion
for /f "tokens=1 delims=$;$" %%a in (formatliste_siegfried.txt) do (
for /f "tokens=1 delims=$;$" %%c in (formatliste_droid.txt) do (
if /i %%a==%%c (
echo match
pause
)
)
)
The problem is that I always get a match even if the appropriate lines are not identical
TL;DR -
Use the fc.exe command.
Details -
There are a few issues with this logic preventing you from getting the output you're looking for. The reason you only get "match" for output is because that is the only possible output - there's only one "echo" line. Adding a case else would output the number of times a line doesn't match.
That said, adding the else would be too noisy to be valuable since the large majority of the output would be "doesn't match". The logic here says "for each line of file 1, check every single line of file 2 to check for a match". For example: given 2 files which each have 100 lines, even if each line had a match in the other file, for each of the 100 outer loops, the output would be 1 "match" and 99 "doesn't match". I'll assume you don't want 100 "match" and 9900 "doesn't match".
So instead, and still considering the question being "how to compare the text lines from two files", I'd recommend using the FC.exe command. Whether batch or vanilla command line, it was designed to compare files.
Other items for consideration:
Missing double quotes around comparison items containing spaces
%%a==%%c ... should be... "%%a"=="%%c"
"delims=" can match nearly any single character, but never a contiguous multi-character group
"Setlocal EnableDelayedExpansion" isn't required as there's no dynamic use of "set"
if case is important, the use of "if /i" will break the integrity of the check

Batch file how to delete end text in a variable string in a for loop

I am writing some batch code to simplify a process I have of downloading some files, renaming them, and then copying them to replace the old ones. I'm running into an issue where I have a FOR loop read in a list of files from a directory, then try to modify the filenames.
The filenames all have FLY in the name, and I want to remove all text after FLY. I can't use tokens because the filenames are inconsistent in length, have multiple spaces, and wouldn't have a set number of tokens. I can't use substring because there is not a set number of characters after FLY.
I've tried using the examples at SS64 and also read numerous threads on here but nothing really seems to match my situation.
Here's the code snippet, appreciate if someone can tell me where I'm going wrong:
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "TOKENS=*" %%A IN ('DIR /B ^"%~DP0VFR^"') DO (
SET FILENAME=%%A
SET REMOVETEXT=!FILENAME:*FLY=!
SET NEWFILENAME=!FILENAME:!REMOVETEXT!=!
ECHO !FILENAME! will be renamed !NEWFILENAME!
)
When I insert echos to see what's going on everything works as expected up until the last SET, where somehow the ending result is !NEWFILENAME! is blank.
Hmm. My results were different from yours.
The " in your dir do not need to be escaped.
The problem with your set statement is that it's interpreted as
SET NEWFILENAME=!FILENAME:! + REMOVETEXT + !=!
and since FILENAME: and = are not existing variables, each will be replaced by nothing yielding "REMOVETEXT", not blank as you claim.
The solution is to use a two-stage evaluation of newname
call SET NEWFILENAME=%%FILENAME:!REMOVETEXT!=%%
which is resolved as
SET NEWFILENAME=%FILENAME:current_value_of_REMOVETEXT=%
in a sub-shell.
After cold brew it occurred to me that I might be going about this all wrong and making it more complicated than it needs to be... I decided to try directly renaming the files with wildcards and that actually worked. Didn't even need the FOR loop.
REN "%~DP0VFR\*FLY*" *FLY
No idea why the first (and overly convoluted) solution I tried didn't work, but this does with a lot less code!

Adjust batch file output to text file

So I´ll explain it a bit here.
I need to create a CSV file but setting the file names one by one is a pain so I was thinking of creating a bat file.
So here's what I have figured out, or actually copied and applied.
In my batch file I got the following code :
dir /b > myFiles.txt
Nice and easy it gives me the following result in the text file:
59019694038.jpg
59019694038_1.jpg
59019694038_2.jpg
59019694038_3.jpg
59019694038_4.jpg
59019694045.jpg
59019694045_1.jpg
59019694045_2.jpg
59019694045_3.jpg
bat.bat
myFiles.txt
But to make things even easier to do I'd like to add a ; after each file it finds.
So the result will be like this :
59019694038.jpg;
59019694038_1.jpg;
59019694038_2.jpg;
59019694038_3.jpg;
59019694038_4.jpg;
59019694045.jpg;
59019694045_1.jpg;
59019694045_2.jpg;
59019694045_3.jpg;
bat.bat;
myFiles.txt;
So my question was if anybody could explain me what I'm currently doing and how I could get this result.
You can replace your DIR ... with:
(FOR %%f IN (*.*) DO #ECHO %%f;)>myFiles.txt
That's a lot easier than parsing file and replacing each line.
If you don't want the line breaks, you can adapt LS_DEV's command:
(FOR %%f IN (*.*) DO #ECHO|set /P=%%f;)>myFiles.txt
Here's an alternative answer which hopefully outputs them on a single line:
#(For %%A In (*) Do #Set/P "=%%A;"<Nul)>"..\myFiles.txt"
In this case I have sent the output to myFiles.txt in the parent of the current directory, just so that it isn't included in it's own results. You can optionally change that to an alternative location or have it included in it's own content if you wish.

Using FINDSTR to search for a pattern and assign it to a variable

I have the following entry in the file Build.aip. I need to write a batch file that searches for "PackageFileName and prints the value assigned for that in the file. In this case, I need to print MyPackageName on the console:
<ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="C:\Build\Build.aip" PackageFileName="MyPackageName" Languages="en" InstallationType="4">
May you please give me some examples how I can do that? I seen in some forums that this can be done using FINDSTR.
Thanks in advance.
findstr "PackageFileName" Build.aip
If you want to make it case insensitive, add the /i argument.
For more details, type findstr /?
Updated for an example to use the for statement
FOR /F "token=2" %i in (`FINDSTR "PackageFileName" Build.aip`) do SET var=%i
A couple things to keep in mind here:
This version is based on Windows 8.1; it may work differently in different versions of Windows.
The token=2 is an example assuming that the word you are looking for is the second word in the line
If PackageFileName appears more than once in Build.aip, this code will break.
The findstring command is surrounded by back-ticks, not single quotes.
I haven't tested it; the SET may not actually survive the for loop. So test!
If you use it in a batch file, you must double all the % signs.

Resources