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 yourgrep
, 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 thewsl.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 of0
when found or1
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 togrep
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 forawk
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 foriconv
to handle this properly as well.