2

Is there a way for a shell script to determine if it is called from a terminal in a virtual machine running Ubuntu, or a W10 terminal using the bash call (installed Ubuntu app in W10)?

I am working in both environments and have a lot of useful shell scripts to make my work more efficient on the virtual machine, e.g. opening specific URLs or running sets of commands. I would like them to work on the Windows side as well. However, my scripts sets up directories which will have to be different on my Windows side.

I have installed the ubuntu app from Windows Store, which allows me to open a bash window and source the files. I could just check if ~ returns an empty string, but is there a more robust way of doing it?

I am running Windows 10, version 17763 and using Ubuntu 18.04 LTS.


E.g.

C:\.sourceThis.sh

#!/bin/bash

myDir="/home/user/stuff"

cdMySub() {
    cd "$myDir/$1"
}

I can run this in a Windows terminal by

C:\> bash
USER@XXXX:/mnt/c/$ source ./.sourceThis.sh
USER@XXXX:/mnt/c/$ cdMySub someSubDirectoryName
-bash: cd: /home/user/stuff/someSubDirectoryname: No such file or directory
USER@XXXX:/mnt/c/$   #Fail!

but it does not work, since the Ubuntu file system is different to Windows.

I would like to change .sourceThis.sh to something like

...
if [[ "Something that detects virtual machine" ]] ; then
    myDir="/home/user/stuff"
elif [[ "Something that detects 'bash' from Windows prompt" ]] ; then
    myDir="/mnt/c/user/stuff"
fi

so that the outcome is instead

C:\> bash
USER@XXXX:/mnt/c/$ source ./.sourceThis.sh
USER@XXXX:/mnt/c/$ cdMySub someSubDirectoryName
USER@XXXX:/mnt/c/stuff/someSubDirectoryName$   #Yeay, success!

EDIT:

I cannot just check for the validity of the default directory, since the scripts create the directory if it does not exist. I want it to point to another default path instead.

I use different user names, so I could check that the output from ~ is the "Windows or VM user".

USER@XXXX:/mnt/c$ echo ~
/home/USER

Thus,

tmpHome=~
if [[ "${tmpHome##*/}" == "USER" ]] ; then
    # Windows user
elif [[ "${tmpHome##*/}" == "VM" ]] ; then
    # VM user
fi

works for my specific user. However, I suspect that I want to use this on different users (e.g. share it with a colleague). This demands a more robust way.

I am not too experience with Linux. I do not know how to navigate the world of users, processes and tasks, which I suspect can give the answer.

4 Answers 4

1

I have used this for a long time successfully:

if [[ "$(uname -r)" == *Microsoft ]]; then
    do stuff
fi
Sign up to request clarification or add additional context in comments.

Comments

1

You could always use an if condition checking whether the path exists, and run the script from there :

if [[ -f /home/user/stuff ]]; do 
  script if running on linux
else
  script if running on windows
fi

Here the -f flags is a bash condition checking whether the file at specified path exists, returns true if it does. You can add other validations to check whether the file also exists when running on Windows and whatnot.

1 Comment

Dexirian, wonderful! That should do the trick! [[ "$(uname -r)" =~ "Microsoft" ]] should be more portable. No unix user would name themself "Microsoft" ;)
1

Bash provides information about the system that is running it it the MACHTYPE, HOSTTYPE, and OSTYPE built-in variables.

Example values for a physical Linux system are:

MACHTYPE=x86_64-redhat-linux-gnu
HOSTTYPE=x86_64
OSTYPE=linux-gnu

Example values for a WSL Linux system are:

MACHTYPE=x86_64-pc-linux-gnu
HOSTTYPE=x86_64
OSTYPE=linux-gnu

One possible way to check if the system is WSL Linux is:

if [[ $MACHTYPE == *-pc-* ]]; then
    ...
fi

1 Comment

@Smartskaft2, I generally prefer to use Bash built-ins instead of external commands when both options are available. There can be advantages in reliability, portability, or performance. However, I don't know enough about the workings of MACHTYPE and uname -r on different platforms to be sure which is the best option in this case. Sorry I can't help any more.
0

@Dexirian and @Michael Hoffman suggested a method that worked!


For me uname -r returns x.x.x-17763-Microsoft from the Windows prompt and x.x.x-xx-generic on my virtual machine.

Thus,

if [[ "$(uname -r)" =~ "Microsoft" ]] ; then
    myDir="/mnt/c/user/stuff"
elseif [[ "$(uname -r)" =~ "generic" ]] ; then
    myDir="/home/user/stuff"
fi

works like a charm!

1 Comment

My answer relies the fact that no other Unix kernel creator will put Microsoft at the end of the name of their kernel release. It doesn't have to do with usernames.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.