Batch脚本FOR循环仅设置输出的第一个字母:wsl –list -q

huangapple go评论77阅读模式
英文:

Batch script FOR loop only setting the first letter of the output wsl --list -q

问题

@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
英文:

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: https://stackoverflow.com/questions/6359820/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.

答案1

得分: 1

这里有两个步骤:

  • wsl --list 的输出从UTF-16-LE转换为其他格式
  • 从结果输出中获取发行版的版本信息

WSL的命令行界面对于第二个步骤并没有提供优雅的解决方案。然而,如果您的PC上只有Ubuntu映像,那么这些映像可以很容易地使用 delims=- 进行标记,因为它们都使用相同的格式进行命名。不过,处理结果的字符编码完全是另一回事,因为cmd.exe没有提供将文本从一种编码转换为另一种编码的简单方法。也就是说,如果再次运行 wsl --list -q 有任何输出,那么您确实安装了一些WSL发行版,从而可以访问 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
        )
    )
)

之后,可以像这样使用数组:

for /l %%i in (1, 1, %distros%) do (
    echo(!distros[%%~i]!
)
英文:

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]!
)

答案2

得分: 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.

英文:

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.

huangapple
  • 本文由 发表于 2023年5月11日 06:13:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76222901.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定