I have a feeling I'm missing something incredibly simple
Not really. In my experience, calling one scripting language from another is rarely what-I-would-call "simple" ;-).
That's a good attempt to figure it out from the help, but unfortunately there's just not enough detail in the wsl --help output to figure it out from that.
As noted in the help, though, there are a few constructs available for running commands in a WSL instance using the wsl.exe command.
wsl <commandline>: Runs the command line as an argument to the default shell.
wsl -e <command>: Runs the command in place of the shell
Note that, for the sake of safety, I'm going to replace your command-lines with more benign versions ;-).
for f in $(find -xdev -type l); do echo $f "----" $(readlink $f); done
Side note: As someone once pointed out to me when I used find with for -- Why is looping over find's output bad practice?, so it would really be better off as find -xdev -type l | xargs -I % sh -c "echo -n % '---- '; readlink %", but we're going to leave it in a for loop to demonstrate part of the problem here.
The following two tries fail because ...
wsl --cd ~ -c 'for f in $(find -xdev -type l); do readlink $f; done'
-c is not a flag that is understood by wsl.exe
wsl.exe --cd ~ 'for f in $(find -xdev -type l); do readlink $f; done'
That would be the equivalent of running cd ~; for f in $(find -xdev -type l); do readlink $f; done, which won't work either, of course.
Actually, in retrospect, this might work for you. It failed for me because my default shell is Fish, but wsl does seem to attempt to run the default shell with -c for whatever command-line is passed in.
It may have failed for you because you weren't setting the directory (via --cd) on the same command-line before calling it.
wsl.exe --cd ~ -e 'for f in $(find -xdev -type l); do readlink $f; done'
And, while you didn't mention trying this, this particular one won't work either, since -e needs to be a single "command", but that's a full commandline with shell builtins such as for.
"Aaargggh!", you've been saying, right? Catch 22? You need -c to get to the shell, but the wsl command can't pass it.
So, we use:
wsl --cd ~ -e sh -c 'for f in $(find -xdev -type l); do echo $f "----" $(readlink $f); done'
That:
- Changes to the home directory (you can replace with the
$FOLDER variable from PowerShell, of course)
- Executes the
sh shell (you could also use Bash (or any other shell or command) if you need any of its constructs)
- Passes the commandline via
-c to the shell. This is a fairly normal argument for most shells, POSIX or otherwise.
Note (from experience) that quoting rules between PowerShell and WSL/sh can get fairly "unruly". I find that as the example gets more complicated, it's often better to put the shell commands in a script inside WSL, which you then execute from PowerShell. For example, something like:
wsl --cd ~ -e sh -c "~/.local/bin/myscript.sh"
--cd note
Using two separate wsl commands, like in your --cd example:
wsl.exe --cd $Folder
wsl.exe echo "Hello World" # Never executes
Assuming you were executing that via a script, the first line:
- Changes to the specified directory
- Runs the default shell, so you are then in an interactive session
If you then exit the shell (Ctrl+D or exit), then you should see the output from the second command.
You can also see this interactively if you run it from PowerShell via:
wsl --cd ~ ; wsl echo Hello
-coption (thereforewsl -cprobably won't work), and you must pass it an executable (foris not an executable). What happens if you do awsl /usr/bin/unameor, for instance, awsl bash -c echo hello world? Do you get at least an error message?wsl bash -c echo hello worldoutputs nothing in both Powershell and Command Prompt.unamethe same?wslinto windows command prompt, or a powershell terminal, I get a bash prompt. Doesn't matter if I specify the full path to wsl or just wsl. I'm positive I'm running the correct wsl.