I am trying to append a backslash to the end of a string (a folder name), and instead of getting a backslash, I seem to be getting a line break, 13 spaces, then finally the backslash. Where is this coming from?
Here is the code I wrote:
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: After the user chooses a folder from a menu, the choice is stored in ChosenFolder
:: A typical value for ChosenFolder would be "3 .\Folder1"
set "ParentFolder=!ChosenFolder:~2!^\"
echo ParentFolder is !ParentFolder!
The output I get is:
ParentFolder is .\Folder1
\
If I just manually set the ChosenFolder variable to "3 .\Folder", this error doesn't happen, so here is the code that ultimately generates the faulty value of ChosenFolder (a slightly modified version of Magoo's code that answered this question, bless his heart!)
SET "choicenames=z0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"
:: remove variables starting #
FOR /F "delims==" %%e In ('set # 2^>Nul') DO SET "%%e="
FOR /L %%e IN (1,1,%pagewidth%) DO SET "#spaces=!#spaces! "
:: Read dirnames to #nn, count to #entries
FOR /d %%e IN ("%~1\*.") DO SET /a #entries =1&SET "#!#entries!=%%e"
SET /a #entries =1&SET "#!#entries!=z Quit."
SET /a #columns=(#entries pagesize - 1) / pagesize
SET /a #rows=(#entries #columns - 1)/#columns
SET /a #columnwidth=(pagewidth/#columns) - 3
SET "#choices=z"
FOR /L %%e IN (1,1,%#entries%) DO (
rem column contents - max length terminal spaces
IF %%e neq %#entries% (
SET "#%%e=!#%%e:~-%#columnwidth%!%#spaces%"
SET "#%%e=!choicenames:~%%e,1! !#%%e:~0,%#columnwidth%!"
SET "#choices=!#choices!!choicenames:~%%e,1!"
)
)
FOR /L %%e IN (1,1,%#rows%) DO (
SET /a cols=%%e %#rows%
SET /a #line=%%e (%#rows% * 2^)
SET "cols=!cols! !#line!"
SET "#line=!#%%e!"
FOR %%y IN (!cols!) DO IF DEFINED #%%y SET "#line=!#line! !#%%y!"
ECHO !#line!
)
IF %#entries% gtr 36 (
choice /cs /c %#choices%
) ELSE (
choice /c %#choices%
)
IF ERRORLEVEL 2 (
ECHO ERRORLEVEL is %ERRORLEVEL%
SET /a #choices=%ERRORLEVEL%-1
CALL SET "ChosenFolder=%%#!#choices!%%"
ECHO choice made : !ChosenFolder:~2!
CHOICE /C snc /N /M "(S)elect, (N)avigate or (C)ancel? "
IF errorlevel 3 goto begin
IF errorlevel 2 CALL :SelectFolder !ChosenFolder:~2!
IF errorlevel 1 EXIT /B 0
) ELSE GOTO begin
CodePudding user response:
#?
contains the name as, eg : 3 u:\Folder1
. The spaces are added to lay out the menu appropriately, so they would need to be deleted (hence the series of spaces when manipulated and the need to lop off the leading 2 characters).
\
does not need to be escaped if simply appended to the string.
Note however - Use set "var=value"
for setting string values - this avoids problems caused by trailing spaces. Don't assign "
or a terminal backslash or Space. Build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value"
is used, then the quotes become part of the value assigned.
FOR /d %%e IN ("%~1\*.") DO SET /a #entries =1&SET "#!#entries!=%%e"&SET "#originalnames!#entries!=%%e"
To establish a parallel list of names, #originalnames?
.
IF ERRORLEVEL 2 (
ECHO ERRORLEVEL is %ERRORLEVEL%
SET /a #choices=%ERRORLEVEL%-1
CALL SET "ChosenFolder=%%#originalnames!#choices!%%"
ECHO choice made : !ChosenFolder!
CHOICE /C snc /N /M "(S)elect, (N)avigate or (C)ancel? "
IF errorlevel 3 goto begin
IF errorlevel 2 CALL :SelectFolder
rem IF errorlevel 1 EXIT /B 0
) ELSE GOTO begin
GOTO :EOF
:selectfolder
ECHO %chosenfolder%
FOR /f "delims=" %%e in ("%chosenfolder%") do SET "Parentfolder=%%~dpe"
echo ParentFolder of %chosenfolder% is %ParentFolder%
GOTO :eof
(Note
on either end of the names to show absence of spaces.)
This assigns the original name (not the displayed name which may have been truncated) to chosenfolder
.
Since chosenfolder
is not within (...)
(ie. a code block) you can use %chosenfolder%
to access its contents. !chosenfolder!
will also work, but it implies that the value of chosenfolder
may vary because it's within a code block - but within the subroutine :SelectFolder
there are no code blocks.
chosenfolder
is of the form u:\folder 1
. so the for
assigns this to %%e
and the parser then interprets u:\folder 1
as drive=u:
, path=\
and filename=folder 1