Last active
July 4, 2020 20:15
-
-
Save Artoria2e5/d398dcbbde037ea115566855860e053a to your computer and use it in GitHub Desktop.
Copy a minecraft directory with some symlinks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# duplicate-minecraft-dir: copies a minecraft directory with some symlinks. | |
# Requires uname and GNU coreutils. | |
# Requires admin priv under Windows. | |
# Dedicated to the public domain under Creative Commons Zero. Do what the heck you wanna do with it. | |
SELF=$0 | |
die(){ printf '%s: %s\n' "$SELF" "$1">&2; exit "${2-2}"; } | |
log() { local level=$1; if ((VERBOSE >= level)); then printf '%s: %s\n' "$SELF" "$2">&2; fi; } | |
nolink=(config options\*.txt launcher_profiles.json servers.dat config baritone Impact mods) | |
is_windows_admin() { id -G | grep -qE '\<(114|544)\>'; } | |
case $(uname -o) in | |
Cygwin) | |
is_windows_admin || die "Gonna need admin privs. Run cygwin as admin!" | |
export CYGWIN+=' winsymlinks:nativestrict';; | |
Msys) | |
is_windows_admin || die "Gonna need admin privs. Run msys as admin!" | |
export MSYS+=' winsymlinks:nativestrict';; | |
esac | |
usage="Usage: $0 [options] [--] SOURCE TARGET | |
Copy the minecraft profile in SOURCE to TARGET, allowing for sharing jars and assets by symlinking" | |
help="Options: | |
-h Displays this help. | |
-a FILE Remove exclusion (a glob). | |
-e FILE Add exclusion (a glob). | |
-v Be verbose. | |
Default exclusions: ${nolink[*]}." | |
VERBOSE=0 | |
while getopts ':haev' opt; do | |
case $opt in | |
(v) ((VERBOSE++));; | |
(a) for i in "${!nolink[@]}"; do | |
if [[ ${nolink[i]} = "$OPTARG" ]]; then | |
unset 'nolink[i]' | |
fi | |
done;; | |
(e) nolink+=("$OPTARG");; | |
(h) printf '%s\n\n%s\n' "$usage" "$help" | |
exit 0;; | |
(*) printf '%s: Invalid option -%s\n%s\n' "$0" "$OPTARG" "$usage">&2 | |
exit 2;; | |
esac | |
done | |
shift "$((OPTIND - 1))" | |
SOURCE=$1 | |
TARGET=$2 | |
assert_is_directory() { | |
if [[ ! -d $1 ]]; then | |
die "$(printf '%q is not a directory' "$1")" 1 | |
fi | |
} | |
assert_is_directory "$SOURCE" | |
mkdir -p -- "$TARGET" | |
printf '%q ' "$@" | |
# find GNU cp | |
declare CP LN | |
is_gnu_command() { "$1" --version &>/dev/null; } | |
find_gnu_command() { | |
declare -n VAR=${1^^} | |
local i | |
for i in "$1" g"$1"; do | |
if is_gnu_command "$i"; then | |
VAR=$i | |
return 0; | |
fi | |
done | |
die "Cannot find GNU $1" | |
} | |
find_gnu_command cp | |
find_gnu_command ln | |
is_nolink() { | |
local needle=$1 i | |
for i in "${nolink[@]}"; do | |
if [[ $needle == */$i ]]; then | |
return 0; | |
fi | |
done | |
return 1 | |
} | |
trouble() { | |
local ret=$? | |
if ((ret > 0)); then | |
log 0 "Trouble -- $1 returned $ret." | |
fi | |
} | |
shopt -s dotglob nullglob | |
for i in "$SOURCE"/*; do | |
basename="${i#*/}" | |
if is_nolink "$i"; then | |
log 1 "Copying $basename..." | |
# When on Windows, try replacing --reflink=auto with -l. A bit unsafe tho. | |
"$CP" -a --reflink=auto -t "$TARGET" -- "$i" | |
trouble "$CP" | |
else | |
log 1 "Symlinking $basename..." | |
"$LN" -rsf -t "$TARGET" -- "$i" | |
trouble "$LN" | |
fi | |
done | |
log 0 "Done, I think! Check your mods, delete old ones and stuff." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment