Skip to content

Instantly share code, notes, and snippets.

@mikeslattery
Last active January 30, 2023 15:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeslattery/5c60655478f76e26b9232aedc664eb7d to your computer and use it in GitHub Desktop.
Save mikeslattery/5c60655478f76e26b9232aedc664eb7d to your computer and use it in GitHub Desktop.
Cross Platform Bash Snippet for Linux, WSL 1, Cygwin, Msys, and GitBash.
#!/bin/bash
# shebang added only to appease shellcheck
# Cross-platform for bash.
# Worry less about when writting a script that must run on Windows and Linux.
# Meant to be used with "source" command in scripts or .bashrc/.zshrc
export USER="${USER:-${USERNAME:-$(whoami)}}"
export USERNAME="${USERNAME:-$USER}"
export HOSTNAME="${HOSTNAME:-${MACHINENAME:-$(hostname)}}"
# Partial x-platform support for: cygpath, xdg-open, winpty, sudo, cmd
if [[ "$(uname -s)" == "Linux" ]]; then
if [[ "$(uname -r)" == *-Microsoft ]]; then
# WSL 1
if ! [[ -d /c ]]; then
echo "/c must be mounted to /mnt/c"
exit 1
fi
export USERPROFILE="${USERPROFILE:-/c/Users/$USER}"
xdg-open() { cmd /c start "$1"; }
if ! command -v cmd &>/dev/null; then
cmd() { /c/Windows/System32/cmd.exe "$@"; }
fi
if ! command -v cygpath &>/dev/null; then
if command -v wslpath &>/dev/null; then
cygpath() { wslpath "$@"; }
else
cygpath() {
if [[ "$1" == "-w" ]]; then
shift
readlink -f "$@" | \
sed -r '/^(\/mnt)?\/[a-z]\b/ { s|/^(\/mnt)?\/([a-z])\b|\U\2:|; s|/|\\|g; }'
else
printf "%s\n" "$@" | sed -r 's|^(.):|/\L\1|; s|\\|/|g;'
fi
}
fi
fi
# Bug workaround
nice() {
if [[ "$1" == "-n" ]]; then shift; shift; fi
"$@"
}
export -f nice
renice() { :; }
export -f renice
else
# Real Linux
if [[ -z "${SSH_CONNECTION:-}" ]]; then
xdg-open() { w3m "$1"; }
fi
export USERPROFILE="${USERPROFILE:-$HOME}"
cmd() { shift; "$@"; }
cygpath() {
if [[ "$1" == "-w" ]]; then shift; fi
readlink -f "$1"
}
if command -v podman &>/dev/null && ! command -v docker &>/dev/null; then
docker() {
PODMAN_USERNS=keep-id podman "$@"
}
fi
fi
winpty() { "$@"; }
else
# Msys / Cygwin
xdg-open() { cmd /c start "$1"; }
sudo() { "$@"; }
export MSYS_NO_PATHCONV=1
export MSYS2_ARG_CONV_EXCL='*'
export COMPOSE_CONVERT_WINDOWS_PATHS=1
if command -v docker &>/dev/null; then
# voodoo magic to make the tty work correctly
docker() {
realdocker="$(command -v docker)"
# --tty or -t requires winpty
#shellcheck disable=SC2140,SC1001,SC2068,SC2145,SC2027
if printf "%s\0" "$@" | grep -ZE '^--tty|^-[^-].*t|^-t.*'; then
winpty /bin/bash -c "xargs -0a <(printf "%s\0" "$@") '$realdocker'"
else
"$realdocker" "$@"
fi
}
export docker
fi
fi
if [[ -n "$TIMEFORMAT" ]]; then
export TIME="$TIMEFORMAT"
export TIMEFMT="$TIMEFORMAT"
fi
# If an ssh connection, connect X back to the host (a MS-Windows X server)
[ -z "$SSH_CLIENT" ] || export DISPLAY="${SSH_CLIENT/ */}:0"
@mikeslattery
Copy link
Author

mikeslattery commented Dec 10, 2018

TODO:

  • kill() - Use taskkill /f /pid for native windows processes and command kill "$@" for msys processs.
  • curl - If Msys, convert paths with cygpath -w
  • curl - wintpy vs password prompt
  • Test with WSL 2
  • MacOS support

I no longer work with Windows, so this isn't maintained much. However, I may get a Mac soon, so I may add support for OSX.

@jmeubank
Copy link

jmeubank commented Feb 22, 2020

$ diff -u x-platform.sh.orig x-platform.sh
--- x-platform.sh.orig  2020-02-23 08:42:55.487752100 -0800
+++ x-platform.sh       2020-02-23 15:57:36.538387800 -0800
@@ -27,12 +27,12 @@
                         shift
                         readlink -f "$@" | \
                             sed -r '/^(\/mnt)?\/[a-z]\b/ { s|/^(\/mnt)?\/([a-z])\b|\U\2:|; s|/|\\|g; }'
-                    elsif
+                    else
                         printf "%s\n" "$@" | sed -r 's|^(.):|/\L\1|; s|\\|/|g;'
                     fi
                 }
-            }
-        }
+            fi
+        fi
         nice() {
             if [[ "$1" == "-n" ]]; then shift; shift; fi
             "$@"
@@ -66,7 +66,7 @@
             realdocker="$(which docker)"
             # --tty or -t requires winpty
             if printf "%s\0" "$@" | grep -ZE '^--tty|^-[^-].*t|^-t.*'; then
-                winpty /bin/bash -c "xargs -0a <(printf "%s\0" "$@") '$realdocker'"
+                command winpty xargs -0a <(printf "%s\0" "$@") "$realdocker"
             else
                 "$realdocker" "$@"
             fi

@mikeslattery
Copy link
Author

@jmeubank Thanks for the fixes.

I can't remember why, but bash -c "xargs..." is necessary as is. It fixes some weirdness with winpty and Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment