0

The following creates a numbered list of links from a remote directory like

1 Link!1
2 Link!2
3 Link!3
4 Link!4
5 Link!5

.

@echo off
setlocal ENABLEDELAYEDEXPANSION

megals --reload /Root/

set /p var1="enter folder name: " & megals /Root/var1

set /a c=0

FOR /F "tokens=1 usebackq" %%i in (`megals -n -e /Root/%%var1%%`) do (
set /a c=c+1
echo !c! %%i 
set string[!c!]=%%i
)

set /P number=Enter number:
echo !string[%number%]!

pause

First Problem: All the links contain a ! character which gets removed by delayedexpansion, rendering the link useless. The links require the ! as it is part of the link.

Second Problem: I'm trying to integrate this into a program, and I can't use findstr because it will list the link and filename on the same line, and when the filenames contain parentheses the program crashes. So I have to use usebackq because it lets me get just the link, without needing to deal with the filenames.

Findstr will list Link!1 Filename (the whole line)

Usebackq lets me just get Link!1

I can't use Findstr because when filenames contain parentheses the program will crash, which can only be solved by delayedexpansion.

This is a follow-up post from here, which I got stuck on: (Shows the Program)
https://stackoverflow.com/questions/49564553/create-a-numbered-list-based-on-a-given-list-of-strings#=

You can see the findstr method there, and how it causes crashes when filenames contain parentheses, which can be fixed with delayedexpansion, but that removes the ! character which is essential as it is part of the link.

Edit: Seems to be working now, thanks

Working Code

@echo off

:start:


megals --reload /Root/

set /p var1="dir? " & megals /Root/%%var1%%

for /f "tokens=1,* delims=:" %%A in ('megals -n /Root/%%var1%% ^|findstr
/n "." ') do (
set Link[%%A]=%%B
Echo %%A %%B
)

setlocal DisABLEDELAYEDEXPANSION

set /a c=0

FOR /F "tokens=1 usebackq" %%i in (`megals -n -e /Root/%%var1%%`) do (
set /a c+=1
call set "string[%%c%%]=%%i"
)

set /P number="Enter number: "

FOR /F "tokens=*" %%g IN ('call echo %%string[%number%]%%') do (SET VAR2=%%g)
echo %Var2%
echo.

Megadl %VAR2% & echo. && goto :start:

pause

https://megatools.megous.com/man/megals.html#_megatools

Jim Jamil
  • 55
  • 8
  • how about just escaping the `!` ? – Gerhard May 17 '18 at 16:56
  • @gerhard-barnard Where? – Jim Jamil May 17 '18 at 17:14
  • Your question is unclear. `usebackq` does not remove any `!` symbols, it just controls which type of quotes [`for /F`](http://ss64.com/nt/for_f.html) uses for what source of data to parse. The part `megals -n -e /Root/%%var1%%` expands to `megals -n -e /Root/%var1%`, which is literally the command executed by `for /F`, but I guess you want `var1` to become expanded. Anyway, to preserve `!` marks you need to toggle delayed expansion so that it is disabled every time some type of `%`-expansion (also for `for` variables) happens... – aschipfl May 17 '18 at 17:16
  • I can't disable delayed expansion because the c counter is part of the FOR loop, and uses it. – Jim Jamil May 17 '18 at 17:23
  • @Mofi Yes LotPings code helped, I updated the OP with the working code. Thanks for your info too. – Jim Jamil May 18 '18 at 06:17

2 Answers2

1

You really should double quote your whole set commands.
Using the alternate delayed expansion type with a call:

@echo off
setlocal DisABLEDELAYEDEXPANSION

megals --reload /Root/

set /p var1="enter folder name: " & megals /Root/var1

set /a c=0

FOR /F "tokens=1 usebackq" %%i in (`megals -n -e /Root/%%var1%%`) do (
    set /a c+=1
    call echo %%c%% %%i 
    call set "string[%%c%%]=%%i"
)

set /P number=Enter number:
call echo %%string[%number%]%%

pause
Gerhard
  • 22,678
  • 7
  • 27
  • 43
  • thanks that does it, but I still need to give the contents of `call echo %%string[%number%]%%` to `Megadl` at the end. So `Megadl` `something` ? @LotPings – Jim Jamil May 18 '18 at 05:22
  • In other words the content of `call echo %%string[%number%]%%` needs to be stored in another variable, which I can then give to `Megadl` to download the link. @LotPings – Jim Jamil May 18 '18 at 05:36
1

The simple solution is not using delayed environment variable expansion, for example by using command CALL.

@echo off
setlocal EnableExtensions DisableDelayedExpansion

megals.exe --reload /Root/

rem Prompt user for folder name and verify that the user has really entered
rem a folder name and remove double quotes to prevent an exit of batch file
rem execution on further processing because of an invalid command line syntax.

:EnterFolder
set "FolderName="
set /P "FolderName=Enter folder name: "
rem Has the user entered anything at all?
if not defined FolderName goto EnterFolder
rem Remove all double quotes from folder name string?
set "FolderName=%FolderName:"=%"
rem Is anything left from folder name after removing double quotes?
if not defined FolderName goto EnterFolder

megals.exe "/Root/%FolderName%"

rem Get first space/tab separated string of each line output by megals
rem assigned to an environment variable which form an array of strings.
rem Redefine end of line character from semicolon to vertical bar as it
rem is impossible that a line starts with a vertical bar. Command CALL
rem is used to double process the SET command line by Windows command
rem processor which is the alternate solution for delayed expansion.

echo/
set "Count=0"
for /F "eol=|" %%I in ('megals.exe -n -e "/Root/%FolderName%"') do (
    set /A Count+=1
    call echo %%Count%% %%~I
    call set "string[%%Count%%]=%%~I"
)

if %Count% == 0 echo There is nothing! & goto EndBatch
echo/

rem Prompt user for number name and verify that the user has really entered
rem a decimal interpreted number which must be in range of 1-%Count%.

:EnterNumber
set "Number="
set /P "Number=Enter number (1-%Count%): "
rem Has the user entered anything at all?
if not defined Number goto EnterNumber
rem Remove all double quotes from number string?
set "Number=%Number:"=%"
rem Is anything left from number string?
if not defined Number goto EnterNumber
rem Contains the number string any non digit character?
for /F "delims=0123456789" %%I in ("%Number%") do goto EnterNumber

rem Remove all leading zeros from number string to avoid interpreting
rem the entered number as octal number on the two IF comparisons below.

:LeadingZeros
if not %Number:~0,1% == 0 goto CheckNumber
set "Number=%Number:~1%"
if defined Number goto LeadingZeros
rem The number was 0 which is less than 1.
goto EnterNumber

rem Check number in range of 1 to %Count% which requires to convert the
rem number strings on both sides of the comparison operators to signed
rem 32-bit integers by Windows command processor in background.

:CheckNumber
if %Number% GTR %Count% goto EnterNumber
if %Number% LSS 1  goto EnterNumber

rem Output the string according to entered number by forcing Windows command
rem processor again to double processing the command line because of CALL.

call echo %%string[%number%]%%

rem Restore previous environment with discarding all the
rem environment variables defined by this batch file.

:EndBatch
endlocal
pause

Another solution is using a subroutine like OutputAndSet.

@echo off
setlocal EnableExtensions DisableDelayedExpansion

megals.exe --reload /Root/

rem Prompt user for folder name and verify that the user has really entered
rem a folder name and remove double quotes to prevent an exit of batch file
rem execution on further processing because of an invalid command line syntax.

:EnterFolder
set "FolderName="
set /P "FolderName=Enter folder name: "
rem Has the user entered anything at all?
if not defined FolderName goto EnterFolder
rem Remove all double quotes from folder name string?
set "FolderName=%FolderName:"=%"
rem Is anything left from folder name after removing double quotes?
if not defined FolderName goto EnterFolder

megals.exe "/Root/%FolderName%"

rem Get first space/tab separated string of each line output by megals
rem assigned to an environment variable which form an array of strings.
rem Redefine end of line character from semicolon to vertical bar as it
rem is impossible that a line starts with a vertical bar. Command CALL
rem is used to double process the SET command line by Windows command
rem processor which is the alternate solution for delayed expansion.

echo/
set "Count=0"
for /F "eol=|" %%I in ('megals.exe -n -e "/Root/%FolderName%"') do call :OutputAndSet "%%~I"

if %Count% == 0 echo There is nothing! & goto EndBatch
echo/

rem Prompt user for number name and verify that the user has really entered
rem a decimal interpreted number which must be in range of 1-%Count%.

:EnterNumber
set "Number="
set /P "Number=Enter number (1-%Count%): "
rem Has the user entered anything at all?
if not defined Number goto EnterNumber
rem Remove all double quotes from number string?
set "Number=%Number:"=%"
rem Is anything left from number string?
if not defined Number goto EnterNumber
rem Contains the number string any non digit character?
for /F "delims=0123456789" %%I in ("%Number%") do goto EnterNumber

rem Remove all leading zeros from number string to avoid interpreting
rem the entered number as octal number on the two IF comparisons below.

:LeadingZeros
if not %Number:~0,1% == 0 goto CheckNumber
set "Number=%Number:~1%"
if defined Number goto LeadingZeros
rem The number was 0 which is less than 1.
goto EnterNumber

:OutputAndSet
set /A Count+=1
echo %Count% %~1
set "string[%Count%]=%~1"
goto :EOF

rem Check number in range of 1 to %Count% which requires to convert the
rem number strings on both sides of the comparison operators to signed
rem 32-bit integers by Windows command processor in background.

:CheckNumber
if %Number% GTR %Count% goto EnterNumber
if %Number% LSS 1  goto EnterNumber

rem Output the string according to entered number by forcing Windows command
rem processor again to double processing the command line because of CALL.

call echo %%string[%number%]%%

rem Restore previous environment with discarding all the
rem environment variables defined by this batch file.
:EndBatch
endlocal
pause

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

See also:

Mofi
  • 46,139
  • 17
  • 80
  • 143