2

I am writing a batch script that copies files from a my windows directory to a WSL distro. Part of this is choosing which distro to copy the files to. If I use the command wsl --list -q if gives me the following output:

Ubuntu-22.04
Ubuntu-18.04

I am trying to use the FOR loop process described in the answer here to assign the variables the distro names: How to set commands output as a variable in a batch file

However, the first variable is always just the first letter of the first line (U) and the second variable is empty.

This is what I have been trying:

@echo off

SETLOCAL ENABLEDELAYEDEXPANSION

SET count=1
FOR /F "tokens=* USEBACKQ" %%F IN (`wsl --list -q`) DO (
SET "var!count!=%%F"
SET /a count=!count!+1
)

ECHO %var1%
ECHO %var2%
ENDLOCAL

Output:

U
ECHO is off.

I have tried removing USEBACKQ, adding delims=, and removing tokens=*. I have also tried using the single variable version in the posted answer. I still only get the U. If I write the wsl --list -q to a .txt file it writes it properly. I'm trying to avoid writing these to a file just to read them and delete the file. I'm wondering if the wsl --list command outputs differently than other commands. The variables properly populated if I used a different command, such as dir.

  • `wsl` output is unicode. I believe the option you are using is `-o`, not `-q` – Magoo May 10 '23 at 23:18
  • `-o` will only give the online versions. `-q` removes extra noise in the output, like a header and the (Default) tag on one of the distros. – PhantomLotus May 11 '23 at 04:29
  • Well, fair enough. I'll assume that I'm using the latest version since I've installed the latest updates on my WIn11 Home system. For me, specifying `-q` yields a help list (as does any invalid parameter, apparently) and `-q` is not mentioned on that list. Naturally, there appears to be no mention of version number. Possibly you are using a server version? – Magoo May 11 '23 at 05:57
  • I am using wsl1 as there were some issues with wsl2 and connecting to the company resources. But I'm not sure if the version would change the list output. – PhantomLotus May 11 '23 at 17:00

2 Answers2

1

There are two steps here:

  • converting wsl --list's output from UTF-16-LE
  • getting distro versions from the resulting output

WSL's CLI doesn't provide an elegant solution to the second step. However, if all you have on your PC are Ubuntu images, then those can be easily tokenized with delims=- as they are named using the same format. Dealing with resulting character encoding is completely different story though, as cmd.exe offers no easy way of converting text from one encoding to another. That said, if - again - wsl --list -q outputs anything, then you do have some WSL distributions installed, and in turn you have access to iconv:

@echo off & setlocal EnableDelayedExpansion

set /a distros=0 >nul

for /f "tokens=1,2,* delims=- " %%i in (
    'wsl --list --quiet ^| wsl --exec iconv -f UTF-16LE -t ASCII'
) do (
    if /i "%%~i"=="Ubuntu" if not "%%~j"=="" (
        set /a distros+=1 >nul 2>&1
        if /i "%%~j"=="Ubuntu" (
            set distros[!distros!]=%%~i
        ) else (
            set distros[!distros!]=%%~i-%%~j
        )
    )
)

Afterwards, the array can be used like so:

for /l %%i in (1, 1, %distros%) do (
    echo(!distros[%%~i]!
)
mataha
  • 155
  • 7
  • This is great, thank you! Is there any feasible way to have this keep the Ubuntu prefix? If not I can work with the version alone (we only use Ubuntu). In any case this solves my problem to a point I can work with it. Thanks! – PhantomLotus May 11 '23 at 23:07
0

My batch for loop wasn't working either with wsl -l. Mataha's answer is impressive, but as of WSL release 0.64.0, you can now set WSL_UTF8=1 in your script.

With that version, the batch becomes as easy as:

@echo off
@setlocal
setx WSL_UTF8 0
set  WSL_UTF8=1
setlocal enabledelayedexpansion
set "command=wsl --list"
for /F "USEBACKQ skip=1 delims=(" %%i in (`%command%`) do (
    set "wslDistro=%%i"
    echo !wslDistro!
)

Just don't make the mistake I did and use setx WSL_UTF8 1 in your environment. That will break VS Code 1.81 because it expects UTF16 when querying the list of distros.

theSparky
  • 440
  • 3
  • 13