Skip to content

Instantly share code, notes, and snippets.

@andkirby
Last active April 29, 2022 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andkirby/3f65c5a6499739c842e25fb7f6d5e682 to your computer and use it in GitHub Desktop.
Save andkirby/3f65c5a6499739c842e25fb7f6d5e682 to your computer and use it in GitHub Desktop.
Download and install node latest NodeJS and Npm on Windows (shell: Git Bash or similar).
#!/usr/bin/env bash
# This script can install NodeJS and NPM on Windows
# Run this command in GitBash Windows console to get latest version:
#
# $ curl -Ls https://gist.github.com/andkirby/raw/node-npm-git-bash-win.sh | bash
#
# Last update: 2022-04-29
set -o errexit
set -o pipefail
set -o nounset
#set -o xtrace
readonly ERR_FATAL=1
readonly ERR_LOGIC=2
readonly ERR_PARAMS=3
# colors
t_red='\e[0;31m'
t_green='\e[0;32m'
t_yellow='\e[0;33m'
t_cyan='\e[0;36m'
t_reset='\e[0m'
echo_head() {
echo -e "${t_green}${@}${t_reset}"
}
echo_note() {
echo -e "${t_cyan}${@}${t_reset}"
}
echo_notice() {
echo -e "${t_yellow}notice:${t_reset} ${@}"
}
echo_warning() {
echo -e "${t_red}warning:${t_reset} ${@}"
}
check_error () {
local status=${1}
shift
if [ '0' != "${status}" ]; then
echo "error: $@" > /dev/stderr
exit ${status}
fi
}
init() {
echo_head ' == Install NodeJS == '
printf 'Making NodeJS home dir ~/.node/...'
mkdir -p ~/.node
init_user_home_bin
}
init_user_home_bin() {
if [ ! -d "${HOME}/bin" ]; then
mkdir -p "${HOME}/bin"
fi
}
is_node_installed() {
test -d ~/.node/${node_name}
}
fetch_node() {
echo 'Fetching NodeJS files...'
releases_url='https://nodejs.org/dist/'
os='win'
os_mode='x64'
# === Download nodeJS ===
# determine version
node_version=$(curl -s ${releases_url} | grep -Eo '>v[^<]+' | tr -d '>/' | sort -V | tail -1)
export node_version
[ -z "${node_version}" ] && check_error ${ERR_LOGIC} 'Cannot find last NodeJS version.'
echo "Found node version: ${node_version}"
export node_name="node-${node_version}-${os}-${os_mode}"
export node_base_dir="${HOME}/.node"
export node_archive="${node_base_dir}/${node_name}.zip"
export node_dir="${node_base_dir}/${node_name}"
if is_node_installed; then
check_error ${ERR_LOGIC} "The node version ${node_name} already installed."
fi
if [[ -e "${node_archive}" ]]; then
echo_notice "Found archive ${node_archive/${HOME}/'~'}. Ignore downloading."
else
curl -s "${releases_url}${node_version}/${node_name}.zip" -o ${node_archive}
echo 'OK'
fi
}
unpack_node() {
mkdir -p ${node_dir}
echo "Unzipping: ${node_archive/${HOME}/'~'}..."
unzip -qq -o ${node_archive} -d ${node_base_dir}
# validate unpacked node.exe
if [ ! -f ${node_dir}/node.exe ]; then
check_error ${ERR_FATAL} "No binary file by path: ${node_dir}/node.exe"
fi
# Remove archive
rm -f ${node_archive}
}
define_binaries() {
export bin_path=${HOME}'/bin'
node_dir_abs=$(echo ${node_dir} | sed -r 's|~|'${HOME}'|g')
###########################################
# Generate binary input files
short_version=$(echo ${node_version} | grep -Eo '([0-9]+)' | head -1)
# bin files for BASH
set_bin 'node.exe' ${short_version}
set_bin 'npm' ${short_version}
set_bin 'npx' ${short_version}
echo_head 'Binary files:'
echo ' EXE: '${node_dir/${HOME}/'~'}'/node.exe'
echo ' '${bin_path/${HOME}/'~'}'/node'
echo ' '${bin_path/${HOME}/'~'}'/node'${short_version}
echo_note ' (Windows CMD)'
echo ' '${bin_path/${HOME}/'~'}'/node.cmd'
echo ' '${bin_path/${HOME}/'~'}'/node'${short_version}'.cmd'
echo_note ' EXE: '${node_dir/${HOME}/'~'}'/npm'
echo ' '${bin_path/${HOME}/'~'}'/npm'
echo ' '${bin_path/${HOME}/'~'}'/npm'${short_version}
echo_note ' (Windows CMD)'
echo ' '${bin_path/${HOME}/'~'}'/npm.cmd'
echo ' '${bin_path/${HOME}/'~'}'/npm'${short_version}'.cmd'
echo_note ' EXE: '${node_dir/${HOME}/'~'}'/npx'
echo ' '${bin_path/${HOME}/'~'}'/npx'
echo ' '${bin_path/${HOME}/'~'}'/npx'${short_version}
echo_note ' (Windows CMD)'
echo ' '${bin_path/${HOME}/'~'}'/npx.cmd'
echo ' '${bin_path/${HOME}/'~'}'/npx'${short_version}'.cmd'
}
set_bin() {
binary_name=$(basename ${1})
short_version=${2}
binary_ref_name="${binary_name%.*}"
# bin files for BASH
cat << EOS > ${bin_path}/${binary_ref_name}
#!/usr/bin/env bash
${node_dir}/${binary_name} \${@}
EOS
if [[ -n "${short_version}" ]]; then
cat << EOS > ${bin_path}/${binary_ref_name}${short_version}
#!/usr/bin/env bash
${node_dir}/${binary_name} \${@}
EOS
fi
# set bin files for native CMD in Windows
node_dir_abs_win=$(echo ${node_dir_abs} | sed -r 's|^[/]([a-z])[/]|\1:/|' | tr '/' '\\')
if [[ -f ${node_dir_abs_win}\\${binary_ref_name}.cmd ]]; then
# set Windows .cmd extension
binary_name=${binary_ref_name}.cmd
fi
cat << EOS > ${bin_path}/${binary_ref_name}.cmd
${node_dir_abs_win}\\${binary_name} %*
EOS
cat << EOS > ${bin_path}/${binary_ref_name}${short_version}.cmd
${node_dir_abs_win}\\${binary_name} %*
EOS
}
######################
# Init
init
fetch_node
unpack_node
define_binaries
@andkirby
Copy link
Author

andkirby commented Sep 7, 2016

To execute this script, run:

curl -Ls https://gist.github.com/andkirby/raw/node-npm-git-bash-win.sh | bash

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