patternMinor
An installer for shell scripts, written in pure sh
Viewed 0 times
scriptswritteninstallerpureshellfor
Problem
I wrote a tiny shell script that basically installs a script into your system by copying it to someplace like
```
#!/bin/sh
set -e
help()
{
echo 'sinister is a simple installer for shell scripts.'
echo
echo 'Usage: sinister -u url [options]'
echo
echo 'Options:'
echo
echo '-?,-h,--help: Print this help and exit.'
echo '-c,--chmod: The mode to chmod your script. Defaults are a+x and u+x.'
echo '-d,--debug: sinister should be run in debug mode.'
echo '-l,--local: The script should be saved for the current user, instead of the entire machine.'
echo '-n,--name: The name of the file the script should be saved to. Mandatory if no URL is given.'
echo '-o,--output: The output directory the script should be saved to.'
echo 'By default this is ~/bin on Unix systems, and C:\Users\you\AppData\Local\script on Windows.'
echo '-u,--url: The location of the script online. e.g: https://github.com/you/repo/raw/master/script'
echo 'If no URL is given the script is read from stdin.'
}
on_windows()
{
uname | grep -q '[CYGWIN|MINGW|MSYS]'
}
per_user()
{
test $LOCAL = 'true'
}
run_powershell()
{
powershell -NoProfile -ExecutionPolicy Bypass "$1"
}
getpath_windows()
{
run_powershell "[Environment]::GetEnvironmentVariable('PATH', '$1')"
}
setpath_windows()
{
run_powershell "[Environment]::SetEnvironmentVariable('PATH', '$1', '$2')"
}
pwd_windows()
{
run_powershell 'Get-Location'
}
CHMOD=
LOCAL='false'
NAME=
OUTPUT=
URL=
test $# -ne 0
while [ $# -gt 0 ]
do
case "$1" in
'-?'|-h|--help) help; exit 0 ;;
-c|--chmod) CHMOD="$2"; shift ;;
-d|--debug) set -x ;;
-l|--local) LOCAL='true' ;;
-n|--name) NAME="$2"; shift ;;
-o|--output) OUTPUT="$2
/usr/local/bin, chmodding it, and adding it to your PATH. It works on both Unix and Windows (via an emulation layer like MSys or Cygwin). Its source code is available on GitHub. Here is the script in its entirety:```
#!/bin/sh
set -e
help()
{
echo 'sinister is a simple installer for shell scripts.'
echo
echo 'Usage: sinister -u url [options]'
echo
echo 'Options:'
echo
echo '-?,-h,--help: Print this help and exit.'
echo '-c,--chmod: The mode to chmod your script. Defaults are a+x and u+x.'
echo '-d,--debug: sinister should be run in debug mode.'
echo '-l,--local: The script should be saved for the current user, instead of the entire machine.'
echo '-n,--name: The name of the file the script should be saved to. Mandatory if no URL is given.'
echo '-o,--output: The output directory the script should be saved to.'
echo 'By default this is ~/bin on Unix systems, and C:\Users\you\AppData\Local\script on Windows.'
echo '-u,--url: The location of the script online. e.g: https://github.com/you/repo/raw/master/script'
echo 'If no URL is given the script is read from stdin.'
}
on_windows()
{
uname | grep -q '[CYGWIN|MINGW|MSYS]'
}
per_user()
{
test $LOCAL = 'true'
}
run_powershell()
{
powershell -NoProfile -ExecutionPolicy Bypass "$1"
}
getpath_windows()
{
run_powershell "[Environment]::GetEnvironmentVariable('PATH', '$1')"
}
setpath_windows()
{
run_powershell "[Environment]::SetEnvironmentVariable('PATH', '$1', '$2')"
}
pwd_windows()
{
run_powershell 'Get-Location'
}
CHMOD=
LOCAL='false'
NAME=
OUTPUT=
URL=
test $# -ne 0
while [ $# -gt 0 ]
do
case "$1" in
'-?'|-h|--help) help; exit 0 ;;
-c|--chmod) CHMOD="$2"; shift ;;
-d|--debug) set -x ;;
-l|--local) LOCAL='true' ;;
-n|--name) NAME="$2"; shift ;;
-o|--output) OUTPUT="$2
Solution
I see a number of things that may help you improve this program. I don't have a Windows machine handy, so these will all be Linux-based observations.
For local installation, don't use
Right now, when the program is created for a local user, the use of
Don't duplicate entries in
Right now, each invocation of your program will cause an additional possibly duplicate line to be added to
Use only POSIX features
Right now the code includes this line:
However, that's not necessarily portable. Instead, use
For local installation, don't use
sudoRight now, when the program is created for a local user, the use of
sudo to copy it means it ends up owned by root. That means that although it's in the local user's bin, they can't run it. For local installation, sudo shouldn't be needed at all and would be a lot safer.Don't duplicate entries in
.profileRight now, each invocation of your program will cause an additional possibly duplicate line to be added to
.profile. Better would be to only add a line if it doesn't yet exist there.Use only POSIX features
Right now the code includes this line:
SCRIPT=$(< /dev/stdin) # read from standard inputHowever, that's not necessarily portable. Instead, use
cat as in:SCRIPT=$(cat /dev/stdin) # read portably from standard inputCode Snippets
SCRIPT=$(< /dev/stdin) # read from standard inputSCRIPT=$(cat /dev/stdin) # read portably from standard inputContext
StackExchange Code Review Q#115204, answer score: 4
Revisions (0)
No revisions yet.