Home > database >  Run sh script with wsl return command not found
Run sh script with wsl return command not found

Time:02-15

I have wsl installed, if from the cmd prompt I run:

wsl ls

it works perfectly, but if if i create a file script.sh and try:

wsl script.sh

with inside:

ls

or any other linux command, I get:

/bin/bash: script.sh: command not found

I have the script in the right folder of course. What causes the issue?

EDIT: Thanks a lot for the answers. Is i possible to associate .sh files to wsl so that they run automatically with double-click?

CodePudding user response:

The general way of launching a script, is not simply script.sh, but:

sh script.sh

So, using wsl, you might try:

wsl sh script.sh

That should do the trick.

CodePudding user response:

Try sh script.sh or you can do ./script.sh, it makes difference and you choose which one works for you.

CodePudding user response:

Sorry, one more answer to the original question. There are more optimal ways to run this than the other answers. There's also still your "root question" of why it's not finding your script when via just wsl script.sh.

When you launch with just:

wsl script.sh

That's essentially launching your default user shell (bash in this case, but it can be changed) with the -c script.sh argument.

You can get a similar result if you run bash -c script.sh from within WSL itself. It will result in the same:

/bin/bash: script.sh: command not found

Or even just running script.sh by itself in bash will result in the same.

... unless script.sh is in your Linux PATH.

However, as another answer pointed out, you can do:

wsl ./script.py

... to correct that particular issue. Just as running ./script.py from that directory from within bash in the first place.

However, an odd sidenote that this actually runs the shell twice in your case:

  • First, WSL loads bash, which is your default shell
  • Then, when bash loads your shell script, it sees that there is no shebang line, so it selects its "default interpreter" for scripts, which is bash itself. It then performs an exec bash script.py to read and process your script.

Note that other shells behave differently. For instance, the Fish shell uses sh as its "default interpreter", and does not exec it, but rather runs it as a subprocess.

Best ways to launch a script using the wsl command-line

The script you mentioned, with just the ls command, is missing a shebang line. Best practice is to start your script with a shebang line which tells the kernel what shell to use when executing the script. For instance, if your script requires bash:

#!/usr/bin/env bash
ls

However, most scripts will run with the lighter-weight "system shell" (e.g. dash under Ubuntu) which is always referenced via sh, so:

#!/usr/bin/env sh
ls

Then you can run your script simply via:

wsl -e script.sh
# or
wsl -e /path/to/script.sh

This executes the script file itself, which then turns around and tells the kernel which shell (or any binary, really) to use to parse it.

Note that if you don't include the shebang line, then you do need to tell WSL which shell to use to launch it. This can be done (again, most optimally) via:

wsl -e sh -c script.sh
# or, it it isn't in your path
wsl -e sh -c /path/to/script.sh
# or substitute bash if needed

The -e argument tells WSL to load that particular argument as the shell, then the -c argument tells the system shell to run your script.

Note that running:

wsl sh script.sh

as suggested in another answer here does work, but if you have a shebang line (as is best-practice), that command will actually load three shells:

  • Loads the default user shell (typically bash), since all wsl <command> commands are passed into the default user shell.
  • Then loads sh as you've asked it to.
  • Then loads whatever shell is on your shebang line.

Hugely inefficient. It works, and you probably won't notice it being a slowdown unless you are running many scripts this way consecutively. But it's easy to do this more efficiently with the -e argument to wsl.exe.

  • Related