5

I'm currently trying to do some batch merging and renaming and am facing the following problem (this is not the actual code, but rather a MWE demonstrating the problem):

@echo off
set /p "arg=Input the path to target directory (defaults to current directory if left empty): "

for %%f in ("%arg%\*.mkv") do (
  echo %%~nf
  set "out=%%~nf"
  echo %out%
)

pause

My problem is that these two echoes do not print the same values. The first one prints the correct thing (file name), the second one prints something random like Echo is OFF or the last file name of the directory.

After a bit of searching I found a mention of using delayed expansion of variables (setlocal EnableDelayedExpansion), but that causes a problem, because the directory path the user inputs may contain exclamation marks, which get removed if I do that (and so the for loop is not executed at all).

How do I properly go about setting variables in a for loop?

UPDATE

With the help of Dennis's solution and some additional trial and error, I was finally able to fix the original code and it now works. For anyone interested, this is what I was attempting to do:

for %%f in ("%arg%\*.mkv") do (
  set "n=%%~nf"

  setlocal EnableDelayedExpansion
  mkvmerge -o "!n:~15,10! !n:~25!" "!n!_Track00.h264" ...
  endlocal
)

The actual command is in fact much longer so I'm not pasting it in its entirety, just pasting enough to demonstrate what is required in it as arguments. I used the variable n because %%~nf does not function well inside the delayed expansion environment (i.e. the !s get removed), and I don't know how to dereference double-percented variables (parameters?) with delayed expansion.

Additionally, attempting to

set "out=%n:~15,10% %n:~25%"

before setting delayed expansion and then running

mkvmerge -o "!out!" ...

did not delay expansion properly so the above code was what I ended up with.

3
  • You should use ! instead of % inside the for-loop, so echo !out!. I suggest looking here Commented Jan 10, 2016 at 14:00
  • enable delayedexpansion and use ! inside the loop. Commented Jan 10, 2016 at 14:03
  • 1
    Possible duplicate of Batch file variables initialized in a for loop Commented Nov 9, 2017 at 12:16

1 Answer 1

7

You should try this:

@echo off
set "arg=."
set /p "arg=Input the path to target directory (defaults to current directory if left empty): "
for %%f in ("%arg%\*.mkv") do (
  echo %%~nf
  set "out=%%~nf"
  setlocal EnableDelayedExpansion
  echo !out!
  endlocal
)
pause
Sign up to request clarification or add additional context in comments.

6 Comments

I've updated the question. This gives me an error on setlocal recursion depth.
Edited, you need endlocal not setlocal disable
OK, this works better, but still has a problem, as it still deletes exclamation marks in file names (they can also include !s). Is there a way to avoid all removal of question marks in names?
Edited, this should work. I also fixed the "if nothing entered" case.
I've managed to implement this solution into my code. I've updated my question and accepted this answer. Thank you for your help.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.