0

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
fortissimo
  • 51
  • 8
  • 2
    `SET /a #columns=(#entries + paigesize - 1) / pagesize` - paigesize vs pagesize - is that intended to be two different variables or a typo? (Both variables aren't defined in your code) – Stephan Dec 13 '22 at 08:00
  • Hmm, I don't see "paigesize" anywhere in the code I pasted, nor can I find that in my original code. Must have been edited by someone else, or if that's not the case, then I don't know where you're getting that. – fortissimo Dec 14 '22 at 05:50
  • Can't find it again. But I literally copy-pasted the command. And two upvotes tell me I've not been the only one who saw it. Anyway - obsolete now. – Stephan Dec 14 '22 at 08:11

1 Answers1

0

#? 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

Magoo
  • 77,302
  • 8
  • 62
  • 84