Home > database >  How to ask WSL to check if the distribution exists, using Bash and `wsl.exe`?
How to ask WSL to check if the distribution exists, using Bash and `wsl.exe`?

Time:06-29

I am trying to ask WSL to check if the distribution exists or doesn't exist, for example, wsl.exe -l -v outputs:

  NAME                   STATE           VERSION
  Arch-Linux             Running         2
* Ubuntu                 Running         2
  docker-desktop         Running         2
  docker-desktop-data    Running         2

I need to ask WSL to check if desktop-desktop-data or Arch exists.

Here is my small Bash code. I tested with several different ways, nothing worked.

# Distribution name: Ubuntu
wsl_distro_name="docker-desktop"

# WSL command to find the distribution name
wsl_command=`wsl.exe -l -v | grep -iq '^$wsl_distro_name' | awk '{print $2}'`

if [[ "$wsl_command" ]]; then
    echo "Distro found"
    exit 0
else
    echo "Not found"
    exit 1
fi

CodePudding user response:

Short answer:

wsl_distro_name="docker-desktop-data"
wsl.exe -l -v | iconv -f UTF-16 | grep -q "\s${wsl_distro_name}\s" && echo "Found" || echo "Not found"

Explanation:

There are a few things going on with your example:

  • First, the thing that probably has you stymied the most is a WSL bug (covered in more detail in this question) that causes the output to be in a mangled UTF-16 encoding. You can see this to some degree with wsl.exe | hexdump -C, which will show the null byte characters after every regular character.

    The solution to that part is to run it through iconv -f utf16. For example:

    wsl.exe -l -v | iconv -f UTF-16
    

I'm guessing you probably introduced some of the following errors into your code while trying to work around the preceding bug:

  • You have $wsl_distro_name in single quotes in your grep, which disables string interpolation in Bash. You need double-quotes there.

  • The ^ won't work at the beginning of the regex since there is whitespace (and/or an asterisk) in the first couple of characters of the wsl.exe -l -v output. Better to use "\s$wsl_distro_name\s to find the distro name that is surrounded by whitespace.

    This will also prevent the expression from finding a "partial" distribution name. Without it, "docker-desktop" would match both "docker-desktop" and/or "docker-desktop-data".

  • grep -q disables output and only returns a status code of 0 when found or 1 if not. Since you are attempting to capture the grep output into $wsl_command, the result will always be empty. You either remove the -q to capture the output or continue to use -q and test the status code.

  • Given your if statement, it seems like you may be expecting the output to be a status result anyway, but testing "$wsl_command" won't work for that, nor will capturing the output via backticks. That would look more like:

    wsl_distro_name="docker-desktop-data"
    wsl.exe -l -v | iconv -f UTF-16 | grep -q "\s${wsl_distro_name}\s"
    if [[ $? -eq 0 ]]; then
        echo Found
    fi
    

    The $? variable holds the exit code of the last command.

    Alternatively:

    wsl_distro_name="docker-desktop-data"
    wsl_distro_result=$(wsl.exe -l -v | iconv -f UTF-16 | grep -o "\s${wsl_distro_name}\s.*" | awk '{print $2}')
    if [[ -n "$wsl_distro_result" ]]; then
        echo "Found ${wsl_distro_name} and it is ${wsl_distro_result}."
    else
        echo "${wsl_distro_name} not found."
    fi
    

    Note that I added the -o option to grep in that snippet. The default distribution will have an asterisk in the first field, which means that we need to "normalize" it so that the second field for awk is always the Status.

  • Finally, recommend using $() rather than backticks. See this question, but note that the POSIX spec says, "the backquoted variety of command substitution is not recommended."

  • Side note: If for some reason you ever need to run this in Alpine, then make sure to install the gnu-libiconv package in order for iconv to handle this properly as well.

  • Related