1

I have a for loop that processes dropped file(s), but I have recently come across a file whose filename includes & and I get an error of & was unexpected at this time. So I am not sure why it's doing it, I have it enclosed in quotes.

Filename example: [This_&_That]_FileName.txt

Small example:

FOR /F "tokens=* delims=;" %%P in ("%*") do call :LOOP %%P

:LOOP

if '%1'=='' goto :endloop

echo %1

pause

....

:endloop

exit

This works fine with spaces, but with the & symbol it crashes. I have to run the .bat file from cmd with the file name as an argument just to see the error.

I have tried enabling delayedexpansion - like in this post and either I didn't do it correctly or it just doesn't work for me: stackoverflow post

Community
  • 1
  • 1
B4NE
  • 13
  • 4

4 Answers4

3

Windows Explorer bug

If a file name does not contain a space character, the explorer doesn't surround it by double quotes for drag & drop actions. As a consequence you can not treat such file names with an ampersand (&) correctly in a batch file.

Assume, you have the following batch script.bat:

@ECHO Off &SETLOCAL
:loop
ECHO "%~1"
SHIFT /1
IF NOT "%~1"=="" GOTO :loop
pause

Make two files, eg. on the command line:

type nul>"This_&_That.txt"
type nul>"This & That.txt"

Now go to the explorer, drag the two files and drop it at your script.bat.
Let's see, what happens:

"C:\TEST\This & That.txt"
"C:\TEST\This_"
press any key to continue . . .


Extended explanation.

Community
  • 1
  • 1
Endoro
  • 37,015
  • 8
  • 50
  • 63
  • thanks but the for statement is still not passing the correct name to the subroutine, it is still cutting off at the "&" symbol – B4NE Jun 29 '13 at 22:38
  • maybe but I am not sure how to apply all of that....as 1, its not going to just be a .txt or .csv file, it is also for 1 or multiple files that I am dropping on the the bat file as to why I am using a /f %*., so how can I implement that so that i can drag and drop any file and it will pass the filename with or without an & symbol to the subroutine – B4NE Jun 29 '13 at 23:02
  • here is a picture of it not working, the test.bat is on my desktop, had have dropped the file from the location shown in the results,[link]http://i.snag.gy/fnGBj.jpg – B4NE Jun 29 '13 at 23:15
  • wow - didn't even occur to me that there would be such a bug - thanks for finding guess i'll just have to rename the files. Thanks again. – B4NE Jun 30 '13 at 02:55
0

You don't need the subroutine :LOOP. Can you live with the quotes around %%P?

FOR /F "tokens=* delims=;" %%P in ("%*") do echo."%%P" & pause
RGuggisberg
  • 4,630
  • 2
  • 18
  • 27
  • Thanks for the quick response, I think I need the sub routine as I am not just printing out the file name...it was just a substitute for here....but I dont care about quotes as long as it works. And if I echo my current %1 (file with no &) the path and file already has quotes around it...which is what i thought the quotes around the %* was doing. so putting quotes around the %%P would not add another set of quotes and make it unreadable? – B4NE Jun 29 '13 at 20:43
  • Yea adding quotes around %%P seems to almost void the quotes around %* and isn't able to process paths / filenames with spaces. – B4NE Jun 29 '13 at 20:50
  • Could you post what you have? I don't know what you are using now (my code without the subroutine or yours with it). – RGuggisberg Jun 29 '13 at 21:02
  • I think if you echo.%%P instead of calling :LOOP yoou will see that it does not have quotes. – RGuggisberg Jun 29 '13 at 21:11
  • I am using the sub: FOR /F "tokens=* delims=;" %%P in ("%*") do call :LOOP %%P :LOOP if "%1"=="" goto :endloop REM ----VARS----- set "f=%~n1" set fn=%f: =_% set var=%tempd%\%fn%_new.txt set var2=%tempd%\%fn%_new2.txt echo "%1" echo. echo %var% echo. echo %var2% pause this is some but in continues on – B4NE Jun 29 '13 at 21:14
  • Ok yes...even by doing this FOR /F "tokens=* delims=;" %%P in ("%*") do echo."%%P" & pause results are "drive\path\\[This_" so it is not processing the full filename to the sub – B4NE Jun 29 '13 at 21:25
0

In this line:

if '%1'=='' goto :endloop

the value of %1 is NOT enclosed in quotes, but in apostrophes. Change it this way:

if "%1"=="" goto :endloop

Of course, you also need to enclose %1 in quotes in the echo command in the subroutine AND around %%P in the calling program, but in this case , the value of %1 woud have the quotes already

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Thanks - stupid mis, but that solves the error...but the processed filename using the above example and echo %1 results: drive\path\\[This_ – B4NE Jun 29 '13 at 21:08
  • and echoing "%1" results in "drive\path\\[This_" – B4NE Jun 29 '13 at 21:09
  • Like i said above putting %1 in quotes in the subroutine still results in the filename from being fully prcessed, it stops at where the & symbol is. – B4NE Jun 29 '13 at 21:20
  • @Aacini the term should be "%~1" in case the filename is quoted. – foxidrive Jun 30 '13 at 09:57
  • @foxidrive: Not exactly. If %%P is enclosed in quotes this way: `call :LOOP "%%P"`, then `%1` is always enclosed in quotes and `%~1` is not, so the program should use the version it needs in each case. However, no one modification solves this problem as Endoro explained in his answer. – Aacini Jun 30 '13 at 11:58
0

Hmmmm.... since I THINK you are we using your code with subroutine... I will ignore the comment about my single line suggestion w/o CALL. We should pick one problem and solve that rather than bounce back and forth. In your example you need to quote the %%P. Typical practice in the subroutine is to do "%~1". The tilde removes quotes and the "" puts them back again if needed. Sometimes they are not needed, but in your case they are needed. Your CALL uses :LOOP and your example used :ENCODE. I will revert to :LOOP.

FOR /F "tokens=* delims=;" %%P in ("%*") do call :LOOP "%%P"

:LOOP
if "%~1"=="" goto :endloop
REM ----VARS-----
set "f=%~n1"
set fn=%f: =_%
set var=%tempd%\%fn%_new.txt
set var2=%tempd%\%fn%_new2.txt
echo "%~1"
echo.
echo %var%
echo.
echo %var2%
pause
REM this is some but in continues on
echo.done & PAUSE
RGuggisberg
  • 4,630
  • 2
  • 18
  • 27
  • Nope... Still by dropping lets say C:\Users\Jim\Desktop\Folder\\[This_&_That]_FileName.txt onto the bat file, results with from the exact code above, "C:\Users\Jim\Desktop\Folder\\[This_" "C:\Users\Jim\Desktop\Folder\tempd"\\[This__new.txt "C:\Users\Jim\Desktop\Folder\tempd"\\[This__new2.txt Press any key to continue... – B4NE Jun 29 '13 at 22:00
  • Ahhh... you need quotes for the other 3 SET commands. set "fn=%f: =_%" set "var=%tempd%\%fn%_new.txt" set "var2=%tempd%\%fn%_new2.txt" – RGuggisberg Jun 29 '13 at 22:05
  • well im not to worried about those, at the moment, as the echo "%~1" is incorrect, meaning those will be incorrect no matter what. but thanks that will probably solve a future issue – B4NE Jun 29 '13 at 22:09