代码拉取完成,页面将自动刷新
#!/bin/bash
# Copyright 2017 bin jin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Framework:
#
# If the function names conform to the specifications:
# External call function.
# Error handling.
# Display help information.
# Print the functions list.
#
# e.g.
# ### [brief_introduction] #[description_1] #[description_1]
# [script_name]_[function_name](){
# ...
# [function_body]
# '''
# # exit and display [error_description]
# exit 1; # [error_description]
# '''
# # return false status
# return 1
# }
### Output version and exit.
_xlib_version () {
printf "0.21.4.11\n" >&2;
return 0
}
### Cursor # ##Usage: cur [option] ## --hide, - hidden cursor# --show, + show cursor ##
_xlib_cur () {
case $1 in
--hide|-)
printf '\033[?25l'
# trap 'printf "\033[?25h"; exit' INT; # show cursor after CTRL-C
;;
--show|+)
printf '\033[?25h'
;;
"")
local p=;
printf '\e[6n';
read -sdR p;
printf "${p#*[}\n"
;;
*)
exit 1; # invalid option
;;
esac
}
### Create/Convert package file ##Usage: pkg [options] [path] ## --dmg, -n [folder] Create DMG # --verify, -t [dmg_file] verify dmg # --dmg2iso, -di [dmg_file_path] Convert a DMG file to ISO # --iso2dmg, -id [iso_file_path] Convert an ISO file to DMG format # --udf, -u [dir_path] Create ISO by directory# --dd, -w [img_path] [disk_path] # Write img to disk # --get, -g [[countdown_min]] Get apk file from AppStore # 1. Login AppStore and Install App # 2. Run this command before download complete # 3. Keep shell open ##
_xlib_pkg () {
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
local tmp;
case $1 in
--dmg|-n)
shift;
[ -d "$1" ] || exit 1; # target folder not found.
# trim, # linux:${1:0:-1} -> darwin:${1:0:${#1}-1}
[ "${1:0-1}" == "/" ] && tmp="${1:0:${#1}-1}" || tmp="$1";
tmp=${tmp##*/};
hdiutil create -srcfolder "$1" -skipunreadable -format UDZO "$tmp.dmg" || return 1
;;
--verify|-t)
shift;
[ "${1##*.}" == "dmg" -o "${1##*.}" == "DMG" ] || exit 1; # format error
hdiutil verify "$1"
;;
--dmg2iso|-di)
shift;
[ -f "$1" ] || exit 1; # dmg file not found
[ "${1##*.}" == "dmg" -o "${1##*.}" == "DMG" ] || exit 1; # file not dmg
tmp=${1##*/};
tmp=${tmp%.*};
hdiutil convert "$1" -format UDTO -o "$tmp.iso";
;;
--iso2dmg|-id)
shift;
[ -f "$1" ] || exit 1; # iso file not found
[ "${1##*.}" == "iso" -o "${1##*.}" == "ISO" ] || exit 1; # file not iso
tmp=${1##*/};
tmp=${tmp%.*};
hdiutil convert "$1" -format UDRW -o "$tmp.dmg";
;;
--udf|-u)
shift;
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
[ -d "$1" ] || exit 1; # directory not found
# hdiutil makehybrid -iso -joliet -o win8.iso win8.cdr
hdiutil makehybrid -udf -udf-version 1.02 -o "$1.iso" "$1";
return 0
;;
--dd|-w)
shift;
# caller 0;
[ -f "$1" ] || exit 1; # img file not found
local target i j k l;
[ "${2:0:9}" == "/dev/disk" ] && {
target=$2
} || {
# cut mount info
while read i j k; do
[ "${k%% (*}" == "$2" ] && target=$i
done < <(mount)
}
# trim
[[ $target == *disk[0-9]s[0-9] ]] && target=${target%s*};
case ${1##*.} in
img)
diskutil unmountDisk $target >/dev/null || exit 1; # Can not unmount this disk
sudo dd if="$1" of=$target bs=4m || exit 1; # dd error
;;
iso)
diskutil unmountDisk $target >/dev/null || exit 1; # Can not unmount this disk
hdiutil convert "$1" -format UDRW -o "${1%.*}.dmg" >/dev/null;
sudo dd if="${1%.*}.dmg" of=$target bs=4m || exit 1; # dd error
rm "${1%.*}.dmg";
# sudo dd if="${1%.*}.dmg" of=$target bs=4m & while killall -USR1 dd; do
# sleep 10;
# done | _xlib_prefix "%F %T, "
;;
gz)
which gzcat >/dev/null 2>&1 || exit 1; # gzcat command not found
diskutil unmountDisk $target >/dev/null || exit 1; # Can not unmount this disk
gzcat "$1" | sudo dd of=$target bs=4m || exit 1; # dd error
;;
xz)
which xzcat >/dev/null 2>&1 || exit 1; # xzcat command not found. try: brew install xz
diskutil unmountDisk $target >/dev/null || exit 1; # Can not unmount this disk
xzcat "$1" | sudo dd of=$target bs=4m || exit 1; # dd error
;;
*)
exit 1; # format not support
;;
esac
sync;
diskutil eject $target >/dev/null
return 0
;;
--get|-g)
__get_pkg $2
;;
*)
exit 1; # invalid option
;;
esac
}
# Get apk file from AppStore
__get_pkg () {
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
# sudo chown -R $USER:`id -gn $USER` /private/var/folders
# sudo chmod -R 755 /private/var/folders
[ `ps -ef | grep -c "${0##*/}.*pkg.*-g"` -gt 3 ] && exit 1; # pkg command is already running
# Override pkg map: pkg[$serial_number]="$path"
function ___get_pkg_serial_number () {
local k v;
while read k v; do
# Put in map
[ "$v" ] && pkg[$k]="$v";
done < <(find "$1" -type f -iname "*.pkg" -exec ls -i {} \; 2>/dev/null); # *.tmp *.pkg
return 0
};
# hash and move to ~/Downloads
function ___get_pkg_complete () {
[ -f "$1" ] || return 1;
local name=${1##*/};
name=${name#*_};
name=${name%.*};
{
printf "NAME: ${1##*/}\n";
printf "SIZE: ";
du -h "$1" | awk '{print $1}'
printf "TIME: ";
_xlib_str --dhms $(($(date +%s) - $sec_on));
_xlib_hash "$1"
mv "$1" ~/Downloads 2>/dev/null || {
cp "$1" ~/Downloads && printf "\033[31m$1 still exist\033[0m\n"
}
} | awk -v name="${name:0:8}, " '{print name $0; fflush(stdout)}'
};
local i anchor count_cache=0 pkg=() tmp=/private/var/tmp store_agent countdown=$((${1-1} * 60 * 5)) sec_on=$(date +%s);
{
printf -v store_agent /private/var/folders/*/*/C/com.apple.appstoreagent/com.apple.appstore;
printf "Will listen \033[4m%s\033[0m sec.\n" $(($countdown / 5));
# Reg hard link from /private/var/tmp
___get_pkg_serial_number "$store_agent";
# Infinite loop
while :; do
# Exit if all download complete
[ $countdown -lt 0 -a ${#pkg[@]} == 0 ] && {
printf "Exit.\n";
break
};
[ $((countdown -= 1)) == 0 ] && printf "Listening \033[4mstop\033[0m.\n";
# Search download pkg
___get_pkg_serial_number "$store_agent";
# foreach pkg array
[ ${#pkg[@]} -gt 0 ] && for i in ${!pkg[@]}; do
# Alleady complete
[ "${pkg[$i]%/*}" == "$tmp" ] && {
___get_pkg_complete "${pkg[$i]}" &
unset pkg[$i];
continue
};
anchor=$tmp/${i}_${pkg[$i]##*/}; # Anchor file path
# Add hard link
[ -f "$anchor" ] || {
ln "${pkg[$i]}" "$anchor" && printf "Add \033[4m${pkg[i]##*/}\033[0m.\n";
};
# Download complete
[ -f "${pkg[$i]}" ] || {
unset pkg[$i];
___get_pkg_complete "$anchor" &
};
done;
[ ${count_cache} != ${#pkg[@]} ] && {
printf "Count: ${#pkg[@]}\n";
count_cache=${#pkg[@]}
};
sleep 0.2
done;
} | _xlib_prefix "%F %T, GPKG, "
# wait all thread over
wait
}
### Wake on LAN ##Usage: wol [MAC_addr] [[broadcast_ipv4]] ## e.g. # wol aa:bb:cc:dd:ee:ff 10.0.0.255 ##
_xlib_wol () {
[ "$1" ] || exit 1; # MAC address is empty
if [ ! "$2" ]; then
[[ $OSTYPE == darwin* ]] && {
route_ip=`route -n get default | awk '/gateway/{print $2}'`;
:
} || route_ip=`ip route | awk '/^default/{if(NR == 1) print $3}'`;
set -- "$1" "${route_ip%.*}.255"
fi
if which perl >/dev/null && [ "${SHELL##*/}" == "bash" -o "${SHELL##*/}" == "zsh" ]; then
printf $(
{
printf 'f%.0s' {1..12};
printf "${1//[:-]/}%.0s" {1..16};
} | sed 's/../\\x&/g'
) | perl -ne 'use Socket; socket(S, AF_INET, SOCK_DGRAM, getprotobyname("udp")); setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1); send(S, $_, 0, pack_sockaddr_in(9, inet_aton("'"$2"'"))); close S' || \
exit 1; # perl error
elif which python >/dev/null; then
python -c 'import socket; S=socket.socket(socket.AF_INET, socket.SOCK_DGRAM); S.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1); S.sendto("".join(["F" * 12, "'"$1"'".replace(":", "").replace("-", "") * 16]).decode("hex"), ("'"$2"'", 9))' || \
exit 1; # python error
else
exit 1; # not support
fi
}
### Remote tools ##Usage: remote [option] [args...] ## -ed25519 [[user@]host] [[alias]] Copy ed25519 public key to remote # -tar [option] [[user@host:]target_path] [[user@host:]source_path] # remote tar command # -scp [pass_word] [command...] Auto scp with password ##
_xlib_remote () {
case $1 in
-ed25519)
shift;
__remote_ed25519 "$@"
;;
-scp)
shift;
__remote_auto_scp "$@"
;;
-tar)
shift;
__remote_tar "$@"
;;
*)
exit 1; # invalid option
;;
esac
}
# for _xlib_remote
__remote_ed25519 () {
[ "$1" ] || exit 1; # first args is empty
local ed25519_pub;
[ -s ~/.ssh/id_ed25519$2.pub ] || ssh-keygen -t ed25519 -P "" -f ~/.ssh/id_ed25519$2;
printf %s 'mkdir ~/.ssh 2>/dev/null;
printf %s "'`cat ~/.ssh/id_ed25519$2.pub 2>/dev/null`'" >> ~/.ssh/authorized_keys;
chmod 600 ~/.ssh/authorized_keys;
chmod 700 ~/.ssh
' | ssh $1 bash || exit 1; # Unknown Error
local host=${1#*@} user;
[ "$host" == "$1" ] && user=${1%@*} || user=$USER;
printf %s "Host $host
HostName $host
Port 22
User $user
IdentityFile ~/.ssh/id_ed25519$2
"
return 0
}
# for _xlib_remote
__remote_auto_scp () {
local password;
password=$1;
shift;
expect <<-TCL
set timeout 150
spawn scp $*
expect {
timeout { exit 2 }
"*yes/no" { send "yes\r"; exp_continue }
"*assword:" { send "$password\r" }
}
expect {
timeout { exit 2 }
"*denied*" { exit 3 }
"No such" { exit 4 }
#### "100%" { exit 0 }
}
expect eof
TCL
case $? in
1)
exit 1; # Expect Error
;;
2)
exit 1; # Time Out
;;
3)
exit 1; # Password Error
;;
4)
exit 1; # File not found
;;
*)
exit 1; # Unknown Error
;;
esac
}
__remote_tar () {
[ "$1" ] || exit 1; # target url is empty
[ "$2" ] || exit 1; # source url is empty
local option="$1" target_host target_dir source_host source_dir;
shift;
target_dir="${1#*:}";
[ "$target_dir" == "$1" ] || target_host=${1%%:*};
# ${target_dir:(-1)} == ${target_dir:0-1}
[ "${target_dir:0-1}" == "/" ] && target_dir="${target_dir:0:${#target_dir}-1}"
source_dir="${2#*:}";
[ "$source_dir" == "$2" ] || source_host=${2%%:*};
[ "${source_dir:0-1}" == "/" ] && source_dir="${source_dir:0:${#source_dir}-1}"
# echo $target_host, $target_dir, $source_host, $source_dir
# return 0
function ___tar_c () {
{
[ "${option/P/}" == "$option" ] && \
printf %s 'cd "'"${2%/*}"'" >/dev/null && tar '$option' - "'"${2##*/}"'"' || \
printf %s 'tar '$option' - "'"$2"'"'
} | ssh $1 bash
};
function ___tar_x () {
[ "${option/P/}" == "$option" ] && {
ssh $1 'cd "'"$2"'" >/dev/null && tar '$option' -'
} || ssh $1 'tar '$option' - '
};
function ___tar_cat_i () {
ssh $1 'cat > "'"$2"'"'
};
function ___tar_cat_o () {
ssh $1 'cat "'"$2"'"'
};
case $option in
*c*)
if [ "$target_host" -a "$source_host" ]; then
# both
___tar_c $source_host "${source_dir}" | ___tar_cat_i $target_host "$target_dir"
elif [ "$target_host" ]; then
# local -> remote
[ -d "$source_dir" ] || exit 1; # source path not found.
{
[ "${option/P/}" == "$option" ] && {
cd "${source_dir%/*}" >/dev/null && tar $option - "${source_dir##*/}"
cd "$OLDPWD"
:
} || tar $option - "${source_dir}"
} | rcat $target_host "$target_dir";
else
# remote -> local
___tar_c $source_host "$source_dir" > "$target_dir";
fi
;;
*x*)
if [ "$target_host" -a "$source_host" ]; then
# both
___tar_cat_o $source_host "${source_dir}" | ___tar_x $target_host "$target_dir"
elif [ "$target_host" ]; then
# local -> remote
[ -f "$source_dir" ] || exit 1; # source file not found.
cat "$source_dir" | ___tar_x $target_host "$target_dir"
else
# remote -> local
cd "$target_dir";
___tar_cat_o $source_host "$source_dir" | tar $option -;
cd "$OLDPWD"
fi
;;
*)
exit 1; # invalid option
;;
esac
return 0
}
### OS globle setting ##Usage: oset [option] [args...] ## --version, -v Get OS version # --allow, -a Allow all app install # --hidden, - [yes|no] Hidden all privite file or directory # --re-launch, -rl Reset LaunchPad # --set-launch, -sl [rows] [cols] # Setting LaunchPad columes rows# --uuid, -u Get uuid by username. default: [current]# --sid, -s Get sid by username. default: [current]##
_xlib_oset () {
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
case $1 in
--version|-v)
which sw_vers >/dev/null 2>&1 && {
sw_vers | awk '{if(/ProductVersion/) {printf $2}; if(/BuildVersion/) print "." $2}';
:
} || system_profiler SPSoftwareDataType | \
awk '/System Version/{gsub(/[()]/, "", $5); print $4 "." $5}'
;;
--allow|-a)
sudo spctl --master-disable;
;;
--hidden|-)
shift;
[ "$1" == "yes" -o "$1" == "no" ] || exit 1; # must select 'yes' or 'no'
defaults write com.apple.finder AppleShowAllFiles $1;
;;
--re-launch|-rl)
defaults write com.apple.dock ResetLaunchPad -bool true;
killall Dock
;;
--set-launch|-sl)
shift;
if [ "$2" ]; then
defaults write com.apple.dock springboard-rows -int $1
defaults write com.apple.dock springboard-columns -int $2
killall Dock
elif [ "$1" ]; then
exit 1; # columns not set
else
defaults write com.apple.dock springboard-rows Default
defaults write com.apple.dock springboard-columns Default
killall Dock
fi
;;
--uuid|-u)
shift;
[ "$1" ] || set "" $USER;
dsmemberutil getuuid -U $1
;;
--sid|-s)
shift;
[ "$1" ] || set "" $USER;
dsmemberutil getsid -U $1
;;
--lock-screen|-l)
# Ctrl + Command + Q
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend
;;
--mobile-sync|--ms)
open ~/Library/Application\ Support/MobileSync/Backup
;;
--logout)
# killall -u $USER;
# kill -9 `ps -Axjc | awk /loginwindow/'{print $2}'`;
# # System Preferences -> Universal Access -> Enable access for assistive devices
# echo a | sudo tee /var/db/.AccessibilityAPIEnabled
# launchctl bootout user/$(id -u $USER)
printf 'tell application "System Events"
log out
end tell
' | osascript
;;
--notify)
shift;
if [ "$3" ]; then
osascript -e 'display notification "'"$1"'" with title "'"$2"'" subtitle "'"$3"'"'
elif [ "$2" ]; then
osascript -e 'display notification "'"$1"'" with title "'"$2"'"'
else
osascript -e 'display notification "'"$1"'" with title "Hi"'
fi
;;
--button-wait)
shift;
osascript -e 'display dialog "'"$1"'" buttons "Yes" with icon note'
;;
--button-choose)
shift;
osascript -e 'display dialog "'"$1"'"'
;;
--set-time)
shift;
if [ "$1" ]; then
date +%m%d%H%M%Y.%S
else
date $1
fi
;;
# Screenshots
# defaults write com.apple.screencapture location $1
# DiskUtil Debug
# defaults write com.apple.DiskUtility DUDebugMenuEnabled 1
# LaunchPad
# defaults write com.apple.dock ResetLaunchPad -bool true; killall Dock
# Spotlight close
# launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist
--sleep)
sudo osascript -e 'tell application "Finder" to sleep'
;;
--allow-app|-aa)
shift;
[ -e "$1" ] || exit 1; # app file not set or found.
sudo spctl --master-disable
sudo xattr -r -d com.apple.quarantine "$1"
;;
--list-users)
dscl . -list /Users UniqueID
;;
*)
exit 1; # invalid option
;;
esac
}
### Certificate tools ##Usage: cert [option] [args...] ## selfsign --host [cn] --email [e] Create certificate for selfsign # rsa [[suffix]] Certificate for rsa ##
_xlib_cert () {
case $1 in
selfsign)
# nginx
shift;
local host email country="CN" state="BJ" city="BJ" company="ORG" section="dev" days=365;
while [ "$2" ]; do
case $1 in
--host|-cn)
# Common Name (eg, YOUR name) []: /CN ($IP / $hostname / $alias)
host="$2";
shift;
shift
;;
--email|-e)
# Email Address []: /emailAddress mail@example.com
email="$2";
shift;
shift
;;
--country|-c)
# Country Name (2 letter code) [AU]: /C
country="$2";
shift;
shift
;;
--state|-st)
# State or Province Name (full name) [Some-State]: /ST
state="$2";
shift;
shift
;;
--city|-l)
# Locality Name (eg, city) []: /L
city="$2";
shift;
shift
;;
--company|-o)
# Organization Name (eg, company) [Internet Widgits Pty Ltd]: /O
company="$2";
shift;
shift
;;
--section|-ou)
# Organizational Unit Name (eg, section) []: /OU
section="$2";
shift;
shift
;;
--days)
days="$2";
shift;
shift
;;
*)
exit 1; # invalid option
;;
esac
done
[ "$host" ] || exit 1; # hostname is empty!
[ "$email" ] || exit 1; # emailAddress is empty!
local SUBJECT="/C=$country/ST=$state/L=$city/O=$company/OU=$section/CN=$host/emailAddress=$email" \
SERVER_CERT="./$host/fullchain.pem" \
SERVER_KEY="./$host/privkey.pem" \
SERVER_CSR="/tmp/${host}_server.csr" \
CA_KEY="/tmp/${host}_ca-cert.pem" \
CA_CERT="./$host/ca.crt";
mkdir -p "$host";
# Create the CA
openssl genrsa -out $CA_KEY 4096;
openssl req -new -x509 -days $days -key $CA_KEY -out $CA_CERT -subj "$SUBJECT";
# Create the Server Key
openssl genrsa -out $SERVER_KEY 4096;
# Create the Server CSR
openssl req -new -key $SERVER_KEY -out $SERVER_CSR -subj "$SUBJECT";
# Self-sign the Server CSR
openssl x509 -req -days $days -in $SERVER_CSR -CA $CA_CERT -CAkey $CA_KEY -set_serial 01 -out $SERVER_CERT;
;;
rsa)
shift;
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa$1;
;;
ed25519)
shift;
ssh-keygen -t ed25519 -P "" -C "$USER@$HOSTNAME" -f ~/.ssh/id_ed25519$1;
;;
*)
exit 1; # invalid option
;;
esac
}
### Display device info
_xlib_drv () {
case $1 in
--info|-v)
if [[ $OSTYPE == darwin* ]]; then
printf ";\n";
system_profiler SPHardwareDataType | \
awk -F : '{if($2 != ""){sub(/^[[:space:]]+/, "", $1); printf "; %+28s %s\n", $1 ":", $2}}'
printf ";\n\n";
else
:
fi
;;
--list|-l)
if [[ $OSTYPE == darwin* ]]; then
# /System/Library/Extensions /Library/Extensions
kextstat
else
:
fi
;;
--refresh|-r)
if [[ $OSTYPE == darwin* ]]; then
sudo kextcache -prune-staging
else
:
fi
;;
*)
exit 1; # invalid option
;;
esac
}
### Print md5,sha1,sha256 checksums ##Usage: hash [file_path] ##
_xlib_hash () {
which openssl >/dev/null 2>&1 || exit 1; # openssl command not found
local h_code;
for h_code in $(
{
[ -f "$1" ] && {
cat "$1" | tee >(openssl dgst -sha1 >&2) >(openssl dgst -md5 >&2) >(openssl dgst -sha256 >&2) | openssl dgst -sha512;
:
} || tee >(openssl dgst -sha1 >&2) >(openssl dgst -md5 >&2) >(openssl dgst -sha256 >&2) | openssl dgst -sha512;
} 2>&1
); do
if [ ${#h_code} == 32 ]; then
printf "MD5: $h_code\n";
elif [ ${#h_code} == 40 ]; then
printf "SHA1: $h_code\n";
elif [ ${#h_code} == 64 ]; then
printf "SHA256: $h_code\n";
elif [ ${#h_code} == 128 ]; then
printf "SHA512: $h_code\n";
fi
done
}
### Volume info or edit ## --wipes, -w [path] Wipes the free space on the volume # --createinstallmedia, -im [device_path] # Create instatll media, by Install*.app
_xlib_vol () {
case $1 in
# --encrypts-all|-eca)
# local args;
# while read args; do
# set $args;
# [ "${2#/Volumes/}" == "$2" ] || diskutil apfs enableFileVault $1 -user disk
# done < <(__vol_list)
# ;;
# --encrypts|-ec)
# __vol_list
# ;;
--wipes|-w)
shift;
[ -d "$1" ] || exit 1; # Target path not found
diskutil secureErase freespace 3 $1
;;
--createinstallmedia|-im)
shift;
[ -d "$1" ] || exit 1; # target device not found
[ -d "$2" ] || set -- "$1" "/Applications/Install";
while read tmp; do
break;
done < <(find "$2"* -iname "createinstallmedia" 2>/dev/null);
[ -f "$tmp" ] || exit 1; # install source not found
[ -f "${tmp%Resources*}SharedSupport/InstallInfo.plist" ] || {
if [ -f "/macOS Install Data/InstallInfo.plist" ]; then
sudo mkdir -p "${tmp%Resources*}SharedSupport";
find "/macOS Install Data" -type f -exec sudo ln {} "${tmp%Resources*}SharedSupport" \;
# else
# exit 1; # need to run the 'install app' and exit before 'reboot'
fi
};
/usr/libexec/PlistBuddy \
-c 'Print :CFBundleDisplayName' \
-c 'Print :DTSDKName' \
-c 'Print :CFBundleShortVersionString' \
-c 'Print :DTSDKBuild' \
"${tmp%Resources*}Info.plist" | awk '{printf $0 " "};END{printf "\n"}'
# sudo "$tmp" --volume "$1" --applicationpath "${tmp%/Contents*}" --nointeraction;
sudo "$tmp" --volume "$1" --nointeraction;
;;
*)
exit 1; # invalid option
;;
esac
}
# __vol_list () {
# local args;
# while read args; do
# set ${args/+->/#} >/dev/null 2>&1 || continue;
# [ "$1" == "|" ] && shift;
# [ $# -le 1 ] && continue;
#
# if [ "$1$2" == "#Volume" ]; then
# printf "$3 $4 "
# # elif [ "$1$2$3" == "APFSVolumeDisk" ]; then
# # printf "$5 "
# elif [ "$1$2" == "MountPoint:" ]; then
# if [ "$3" == "Not" ]; then
# printf %s "- "
# else
# printf "$3 "
# fi
# elif [ "$1" == "FileVault:" ]; then
# printf "$2\n"
# fi
# done < <(diskutil apfs list)
# }
### Directory tools ##Usage: dir [option] [args...] ## --unhidden, -uh [dir_path] No hidden directory # --own [dir_path] Set directory owner # --boot [dir_path] Rebuild boot file # --count, -c [[dir_path]] Get file count # --unique, -u [[dir_path]] Search for duplicate files##
_xlib_dir () {
case $1 in
--unhidden|-uh)
shift;
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
[ -d "$1" ] || exit 1; # target not found or not directory
chflags nohidden "$1"/*;
sudo spctl --master-disable;
;;
--own)
shift;
[ -d "$1" ] || exit 1; # directory not found
local USER arg;
USER=${2:-bin};
# ${1:(-1)} == ${1:0-1}
[ ${1:(-1)} == / ] && arg="${1:0:${#1}-1}" || arg="$1";
sudo chown -R $USER:`id -gn $USER` "$arg" || return 1;
sudo chmod -R 644 "$arg/*"
sudo find "$arg" -type d -exec chmod 755 {} \;
;;
--boot)
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
shift;
[ -f "$1/com.apple.recovery.boot/kernelcache" ] || exit 1; # Boot file not found
sudo bless --folder "$1/com.apple.recovery.boot" --label "Recovery HD";
# 426F6F74-0000-11AA-AA11-00306543ECAC
# [ "${1##*/}" == "dmtest" -a "${2##*/}" == "BaseSystem.dmg" -a -d "$3" ] && "$2" ensureRecoveryPartition "$3" "$2" 0 0 "${2%.*}.chunklist"
;;
--count|-c)
shift;
[ "$1" ] && {
[ -d "$1" ] || exit 1; # target not found or not directory
:
} || set -- \.;
# ls -alR "$1" 2>/dev/null | grep -c '^-'
find "$1" -type f | grep -c '\/'
;;
--unique|-u)
[[ $OSTYPE == darwin* ]] && exit 1; # Not support macOS (OS X)
shift;
# TODO
local i pi size path1 sum name1 temp tmp path_arr=() name_arr=() out=".#Trash";
touch "$out.log" || exit 1; # output error
mkdir -p "$out";
while read size path1; do
[ "$temp" == "$size" ] || {
[ ${#path_arr[@]} -gt 1 ] && \
while read sum name1; do
[ "$sum" ] && printf "${sum:0:8},${name1//%/%%}\n";
[ "$tmp" == "$sum" ] || {
[ ${#name_arr[@]} -gt 1 ] && {
# save first file
unset name_arr[0];
for pi in ${!name_arr[@]}; do
pi="${name_arr[$pi]}";
printf "$temp,MOVE ";
# move file to new file
if [ "$pi" == "${pi%/*}" ]; then
mv -v "./$pi" "$out"
else
mkdir -p "$out/${pi%/*}";
mv -v "./$pi" "$out/${pi%/*}"
fi
done
printf "\n"
};
# sync status
tmp="$sum";
name_arr=()
};
[ -f "$name1" ] && name_arr[${#name_arr[@]}]="$name1"
done < <(
{
for i in ${!path_arr[@]}; do
sha256sum "${path_arr[$i]}" &
done
wait
} | sort --key=1 | uniq --all-repeated --check-chars=64;
printf "\n";
);
# sync status
temp="$size";
path_arr=()
};
[ -f "$path1" ] && path_arr[${#path_arr[@]}]="${path1#*./}";
done < <(
find "${@:-.}" -not -empty -type f -not -iregex ".*$out.*" -printf "%s %p\n" | \
sort --key=1 | \
uniq --all-repeated --check-chars=12;
printf "\n";
) 2>&1 | tee -a $out.log;
;;
*)
exit 1; # invalid option
;;
esac
}
### Lock, Use '-h' for a description of the options #usage: %~n0 lock [option] [...]
_xlib_lock () {
:
}
### String manage ##Usage: str [option] ...## --random, -r [count] Print random string # --lower, -l [str] Convert lower case # --upper, -u [str] Convert upper case # --tac [[file]]# --xmlvalue, -xv [tag_name] Get xml value # --unascii, -ua [dir_path] Print text not in ASCII char # --dhms, -t [secends] Format Unix timestamp to ??d ??h ??m ??s # --passwd, -pw [passwd_str] Get password for stdin chpasswd -e ##
_xlib_str () {
case $1 in
--lower|-l)
shift;
[ "$1" ] && {
tr "[:upper:]" "[:lower:]" <<< "$@"
} || tr "[:upper:]" "[:lower:]";
;;
--upper|-u)
shift;
[ "$1" ] && {
tr "[:lower:]" "[:upper:]" <<< "$@";
} || tr "[:lower:]" "[:upper:]"
;;
--xmlvalue|-xv)
shift;
[ "$1" ] || exit 1; # Args is empty
# grep -oP '(?<=\>)[\d\w_]+(?=\<\/'$1')' && return 0;
perl -ne 'STDOUT->autoflush; print m/(?<=\>)[\d\w_]+(?=\<\/'"$1"')/g, "\n"' && return 0;
return 1
;;
--tac)
shift;
if which perl >/dev/null; then
[ "$1" ] && {
perl -e 'print reverse <>' "$1"
:
} || perl -e 'print reverse <>'
else
[ "$1" ] && {
sed '1!G;h;$!d' "$1"
:
} || sed '1!G;h;$!d'
fi
;;
# --xmltrim|-xt)
# # -xt [text_file_path] Get xml without annotations
# shift;
# awk '/<!--/{i++}/-->/{i--}!i&&!/-->/&&!/^$/' "$@"
# ;;
# --spacetrim|-st)
# -st [text_file_path] Replace all space to one space
# shift;
# [ -f "$1" ] || exit 1; # File not found
# [ "`uname`" == "Linux" ] && {
# sed -r ':1;N;$!b1;s/\s+/ /g' "$1"
# :
# } || perl -i -pe 's/\s+/ /g' "$1"
# ;;
--unascii|-ua)
shift;
if [ -d "$1" ]; then
grep -r '[^[:alnum:][:punct:][:space:]]' "$1";
elif [ -f "$1" ]; then
grep '[^[:alnum:][:punct:][:space:]]' "$1";
else
grep '[^[:alnum:][:punct:][:space:]]'
fi
;;
--now|-n)
date +%Y%m%d%H%M%S
;;
--random|-r)
shift;
# local rand=`dd if=/dev/random bs=1 count=${1:-32} 2>/dev/null | base64 | tr -d '\n'`; # tr -d '\n' support linux
openssl rand -base64 ${1:-9} | tr -d '\n' | sed "s/[^0-9A-Za-z]/${RANDOM:0:1}/g"
;;
--uuid|-u)
uuidgen
;;
--dhms|-t)
shift;
_xlib_inum $1 || exit 1; # Not number
local out=$(($1 % 60))s;
[ $1 -ge 60 ] && {
out=$(($1 % 3600 / 60))m\ $out;
[ $1 -ge 3600 ] && {
out=$(($1 % 86400 / 3600))h\ $out;
[ $1 -ge 86400 ] && out=$(($1 / 86400))d\ $out
}
};
printf "$out\n"
;;
--passwd|-pw)
shift;
which openssl >/dev/null 2>&1 || exit 1; # openssl command not found
[ "$1" ] || exit 1; # Args is empty
openssl passwd -1 "$1"
;;
*)
exit 1; # invalid option
;;
esac
}
### show cpu times.
_xlib_cpu () {
[[ $OSTYPE == darwin* ]] && exit 1; # Not support macOS (OS X)
local REPLY;
while true; do
read < /proc/stat; printf "$REPLY\n";
sleep 1;
done | \
awk '{printf "%s, %5.1f%\n", strftime("%F %T"), (1 - ($5 - idle) / ($1+$2+$3+$4+$5+$6+$7 - totel)) * 100; idle=$5; totel=$1+$2+$3+$4+$5+$6+$7;}'
}
### Show/find IPv4 ##Usage: ip [option] [args...] ## --list, -l Show IPv4 # --find, -f [mac_addr] Search IPv4 by MAC or Host name, # support alias, see lib hosts # --test, -t [str] Test string is ipv4 ##
_xlib_ip () {
case $1 in
--list|-l)
# netstat -rn | grep "default"
local route_ip;
[[ $OSTYPE == darwin* ]] && {
route_ip=`route -n get default | awk '/gateway/{print $2}'`;
ifconfig | awk '/inet '${route_ip%.*}'\.[0-9]+/{print $2}';
:
} || {
route_ip=`ip route | awk '/^default/{if(NR == 1) print $3}'`;
ip addr | awk '/inet '${route_ip%.*}'\.[0-9]+/{print gensub(/\/.*/, "", "", $2)}'
}
;;
--find|-f)
shift;
source "$(cd `dirname $0`; pwd)/bash.xlib";
__ip_find "$@"
;;
--test|-t)
shift;
[ "$1" ] || return 1;
[ ${#1} -gt 15 ] && return 1;
# command test
[ "${1:0:1}" == "-" ] && return 1;
[[ $1 != *[^.0-9]* && $1 == [1-9]*[0-9] && $1 != *..* ]] || return 1;
local a IFS=$IFS".";
a=($1);
[ ${#a[@]} == 4 ] || return 1;
for a in ${a[@]}; do
[ $a -gt 255 ] && return 1;
done
return 0
;;
# convert CIDR Prefix (e.g. 1.1.1.0/24) to Subnet Mask (e.g. 1.1.1.0 255.255.255.0)
# see https://doc.m0n0.ch/quickstartpc/intro-CIDR.html
--cidr2subnet|-c2s)
shift;
[ "$1" ] || exit 1; # arg is empty
set ${1/\// };
local submask i=0 octets=$(($2 / 8)) \
sub_octet=$((256 - 2 ** (8 - ($2 % 8) ) ));
for ((; i < 4; i += 1))
do
if [ $i -lt $octets ]; then
submask+=".255";
elif [ $i == $octets ]; then
submask+=".$sub_octet";
else
submask+=".0"
fi
done
printf "$1 ${submask:1}"
;;
# convert Subnet Mask (e.g. 1.1.1.0 255.255.255.0) to CIDR Prefix (e.g. 1.1.1.0/24)
--subnet2cidr|-s2c)
shift;
[ "$2" ] || exit 1; # arg is empty
function _exponent() {
local base=$1 power=2 exponent=0;
while [ $((base /= $power)) -gt 0 ]; do
((exponent += 1));
done
printf $exponent;
}
local mask prefix=0
for mask in ${2//\./ }; do
(( prefix += 8 - $(_exponent $((256 - $mask))) ))
done
printf $1/$prefix
;;
*)
exit 1; # invalid option
;;
esac
}
# for _xlib_ip
__ip_find () {
[ "$1" ] || exit 1; # MAC address or Host name is empty
# Clear arp cache
[[ $OSTYPE == darwin* ]] && {
sudo arp -ad >/dev/null 2>&1 || return 1;
:
} || arp -n | awk 'NR>1 {system("arp -d "$1)}' || return 1;
local i j max_len=0 r key mac range route_ip;
# get [setting]
__load_ini sip_setting;
route_ip=`_map --get route`;
route_ip=(${route_ip//,/ } `[[ $OSTYPE == darwin* ]] && {
netstat -nr | awk '/^default[[:space:]]/ && ! /tun|tap/{print $2}';
:
} || ip route | awk '/^default/{print $3}'`);
# trim
for i in ${!route_ip[@]}; do
_set --add "${route_ip[$i]%.*}" >/dev/null || unset route_ip[$i];
done
range=`_map --get range`;
[ "$range" ] || range="1-127";
_map --clear;
__load_ini hosts;
local arg mac_addr mac_addr_arr=() tmp;
for arg in "$@"; do
# get from map
mac_addr=`_map --get $arg`;
mac_addr=${mac_addr:-$arg};
# replace separator, skip type like: a-bc
[[ $mac_addr == *-*-*-*-*-* ]] && mac_addr=${mac_addr//-/:};
[[ $mac_addr == *:*:*:*:*:* ]] && {
# cache max variable length
[ ${#arg} -gt $max_len ] && max_len=${#arg};
# convert lowercase
mac_addr=`_xlib_str --lower $mac_addr`;
if [[ $OSTYPE == darwin* ]]; then
# trim ^0, 0a:0b:1c:1d:1e:1f -> a:b:1c:1d:1e:1f
tmp="";
for i in ${mac_addr//|/ }; do
[[ $i == *:*:*:*:*:* ]] && \
for j in {0..9} {a..f}; do
i=${i//0$j/$j}
done
[ "$tmp" ] && tmp="$tmp|$i" || tmp="$i"
done
mac_addr=$tmp;
fi
# add prefix
mac_addr_arr[${#mac_addr_arr[@]}]=$arg@$mac_addr;
}
done
[ ${#mac_addr_arr[@]} == 0 ] && return 0;
# for offset
max_len=$((max_len / 5 * 5 + 5));
# fork: Resource temporarily unavailable
function __match_mac () {
local i j key;
ping -c 2 -t 2 $1 >/dev/null 2>&1;
j=`arp $1 2>/dev/null`;
for mac_addr in ${mac_addr_arr[@]}; do
# cache key
key=${mac_addr%%@*};
# split arr with '|'
mac_addr=(${mac_addr//[@|]/ });
unset mac_addr[0];
for i in ${mac_addr[@]}; do
[[ $j == *$i* ]] && printf "%-${max_len}s$1\n" $key
# Like nbtstat
# [[ `smbutil status $1 2>/dev/null` == *$i* ]] && printf $1
done
done
} 2>/dev/null;
# init thread valve
_thread_valve --init 32;
for r in ${route_ip[@]}; do
for i in `seq ${range/-/ }`; do
# get thread
_thread_valve --run __match_mac ${r%.*}.$i
done
done
# destroy thread valve
_thread_valve --destroy;
# print ipv4 for MAC address not catch
for mac_addr in ${mac_addr_arr[@]}; do
[ "${mac_addr/@/}" == "$mac_addr" -o "${mac_addr/[0-9].[0-9]*.*[0-9].[0-9]/}" == "$mac_addr" ] && continue;
# cache key
key=${mac_addr%%@*};
# split arr with '|'
mac_addr=(${mac_addr//[@|]/ });
unset mac_addr[0];
for i in ${mac_addr[@]}; do
_xlib_ip --test $i && printf "%-${max_len}s$i\n" $key
done
done
# clear arp cache
[[ $OSTYPE == darwin* ]] && {
sudo arp -ad >/dev/null 2>&1 || return 1;
:
} || arp -n | awk 'NR>1 {system("arp -d "$1)}' || return 1;
}
# __hosts () {
# printf %s '##
# # Host Database
# #
# # localhost is used to configure the loopback interface
# # when the system is booting. Do not change this entry.
# ##
# 127.0.0.1 localhost
# 255.255.255.255 broadcasthost
# ::1 localhost
# '
# }
### Update hosts by ini # will read ini config from HOME or script path. # ini file context like: # #[hosts] #abc.org=01-12-23-34-45-56 #lib-233=67-78-89-9a-ab-bc #www.a.com=192.168.1.1 ##
_xlib_hosts () {
source "$(cd `dirname $0`; pwd)/bash.xlib";
# load ini in map1
__load_ini hosts 1 || exit 1; # Not found ini configure
# get map1 key array in MAP2ARRAY
_map 1 --keys;
local i j k line host_new lf;
printf -v lf "\n";
while read line; do
# override mac address in map1, if value not ipv4
_xlib_ip --test "$(_map 1 --get ${line%% *})" || {
_map 1 --put $line >/dev/null;
printf "%s\n" "$line"
}
done < <(_xlib_ip --find ${MAP2ARRAY[@]});
# clear map0, sip command use it before
_map --clear;
# get map1 key value in MAP2ARRAY
_map 1 --arr || exit 1; # Unknown error
for ((i=0; i<${#MAP2ARRAY[@]}; i+=2)); do
_xlib_ip --test ${MAP2ARRAY[i + 1]} && _map --put "${MAP2ARRAY[$i]}" "${MAP2ARRAY[i + 1]}" >/dev/null;
done
while read line; do
k=($line);
j=`_map --get "${k[1]}"` && {
_map --remove "${k[1]}" >/dev/null;
[ "$j" == "$k" ] || {
host_new+="${line/$k/$j}$lf";
continue
};
}
host_new+="$line$lf";
done < <(cat /etc/hosts);
# empty array
_map --arr || unset MAP2ARRAY;
for ((i=0; i<${#MAP2ARRAY[@]}; i+=2)); do
host_new+="${MAP2ARRAY[i + 1]} ${MAP2ARRAY[i]}$lf"
done
printf %s "$host_new" | sudo tee /etc/hosts >/dev/null
}
# # Test mac address
# __imac () {
# [ "$1" ] || return 1;
# # command test
# [ "${1:0:1}" == "-" ] && return 1;
# [[ $1 != *[^-:0-9a-fA-F]* && $1 != *--* && $1 != *::* && $1 == [0-9a-fA-F]*[0-9a-fA-F] && $1 != *[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]* ]] || return 1
# local a IFS=$IFS":-";
# a=($1);
# [ ${#a[@]} == 6 ] || return 1;
# return 0
# }
### Connect vnc server ##Usage: vnc [ipv4][:[port]] ##server listening port 5900 ##
_xlib_vnc () {
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
_xlib_ip --test $1 || exit 1; # Args not a ipv4
open vnc://$1;
return 0
}
### Start a disposable http server ##Usage: httpd [port] [[file_path]]
_xlib_httpd () {
_xlib_inum $1 || exit 1; # arg not a port
if [ -s "$2" ]; then
{
printf "HTTP/1.1 200 OK\n\n";
cat "$2";
} | nc -l $1
else
printf "HTTP/1.1 200 OK\n\nNETCAT\n" | nc -l $1
fi
}
### Test str is num ##Usage: inum [str] ##
_xlib_inum () {
[ "$1" ] || return 2;
[[ $1 != *[^0-9]* && $1 != 0[0-9]* ]] || return 1;
return 0
}
### Tag prefix each line, support `date` format ##Usage: [command] | prefix [strftime format] ##
_xlib_prefix () {
[ "$1" ] || exit 1; # Args is empty
source "$(cd `dirname $0`; pwd)/bash.xlib";
_prefix "$@"
}
### Plist editer ##Usage: plist [option] [path...] ## --xml, -x [plist_path] print plist as xml format # --json, -j [plist_path] print plist as xml format # --binary, -b [plist_path] serialize plist to stdout # --load [plist_path] load plist # --unload [plist_path] unload plist ##
_xlib_plist () {
[[ $OSTYPE == darwin* ]] || exit 1; # Only support macOS (OS X)
# plutil defaults /usr/libexec/PlistBuddy
which plutil >/dev/null 2>&1 || xcode-select --install 2>/dev/null
[ $# -lt 2 ] && exit 1; # invalid option
[ "${2##*.}" == "plist" ] || exit 1; # file format not support
case $1 in
--get|-g)
shift;
[ -f "$1" ] || exit 1; # file not exist
[ "$2" ] || exit 1; # key not exist
defaults read "$1" "$2"
;;
--xml|-x)
shift;
[ -f "$1" ] || exit 1; # file not exist
plutil -convert xml1 "$1" -o - || exit 1; # plutil error
;;
--json|-j)
shift;
[ -f "$1" ] || exit 1; # file not exist
plutil -convert json -r "$1" -o - || exit 1; # plutil error
printf "\n"
;;
--binary|-b)
shift;
[ -f "$1" ] && exit 1; # file aleady exist
sudo plutil -convert binary1 -o "$1" - || exit 1; # plutil error
;;
--load)
shift;
[ -f "$1" ] || exit 1; # file not exist
sudo launchctl load -wF "$1"
;;
--unload)
shift;
[ -f "$1" ] || exit 1; # file not exist
sudo launchctl unload -w "$1"
;;
*)
exit 1; # invalid option
;;
esac
}
# __file_sub_time () {
# [ -f "$1" ] || return 1;
# printf $(( (`date +%s` - `stat -f "%a" "$1"`) / 60 / 60 ))
# }
# load .*.ini config
__load_ini () {
[ "$1" ] || return 1;
local line is_catch=false;
while read line; do
[ "$line" == "" ] && continue;
if [ "${line/=/}" == "$line" ]; then
[ "$line" == "[$1]" ] && is_catch=true || is_catch=false;
elif $is_catch; then
_map $2 --put ${line%%=*} ${line#*=} >/dev/null
fi
done < <(cat ${0%/*}/.*.ini ~/.*.ini 2>/dev/null | awk -F \; 'gsub(/\r|\\$/, ""); gsub(/\\/, "\\\\"); {print $1}' | uniq);
# # read environment variable
# while read line; do
# [ "$line" == "" -o "${line/=/}" == "$line" ] && continue;
# _xlib_ip --test ${line#*=} || {
# __imac ${line#*=} || continue
# };
# _map $2 --put "${line%%=*}" "${line#*=}" >/dev/null;
# done < <(set);
[ `_map $2 --size` == 0 ] && return 1;
return 0
}
# # args path size(MB)
# __ramfs () {
# # https://gist.github.com/Roman2K/3238fb441e298369198e
# case $1 in
# --mount|-m)
# # hdid = hdiutil attach
# local ramfs_dev=`hdid -nomount ram://$(($3 * 1024 * 1024 / 512))`;
# newfs_hfs -v "ramfs" ${ramfs_dev};
# mkdir -p "$2";
# # mount -o nobrowse -t hfs ${ramfs_dev} "$2"
# mount -o noatime -t hfs ${ramfs_dev} "$2"
# ;;
# --umount|-u)
# ramfs_dev=`df "$2" | tail -1 | awk '{ print $1 }'`;
# umount "$2";
# hdiutil detach ${ramfs_dev}
# ;;
# *)
# printf "\033[31m$1: invalid option\033[0m\n" >&2
# ;;
# esac
# }
#################################################
# Framework #
# # # # # # # # # # # # # # # # # # # # # # # # #
# Print Error info
_func_err () {
[[ "$4$6" == exit_${0##*/}* ]] && {
# local err=`awk 'NR=='$2'{print}' "$0"`;
local err=`sed -n $2p "$0"`
# Print line text after '#'
printf "\033[31mError:${err##*#} \033[33m($0:$2)\033[0m\n" >&2;
exit $(($5 % 256))
};
# WARRAN: 0 <= $? <= 255, return 256: $? = 0
[ "$4" == "return" ] && exit $(($5 % 256));
# Get script line
[ $1 == 127 ] && {
# No function found
printf "\033[31mError: No function found \033[0m\n" >&2;
exit 1
};
exit 0
}
# Show function info
_func_annotation () {
local i j k OLDIFS IFS=$IFS\({;
# Cache IFS
OLDIFS=$IFS;
if [ "$1" ]; then
# show select
while read i j; do
# Make array splite with #
[ "$i" == "###" ] && {
IFS=#;
k=($j);
# Reset IFS
IFS=$OLDIFS
};
# At target func name
[ "$k" -a "$i" == "_${0##*/}_$1" ] && {
# Print all annotation
for i in ${!k[@]}; do
printf "${k[$i]}\n";
done;
return 0
};
# Reset var
[[ "$i" == _${0##*/}* ]] && [ "$j" == ")" ] && unset k;
done < "$0"; # Scan this script
return 1
else
# show all
while read i j; do
# Cache intro
[ "$i" == "###" ] && k=${j%%#*};
# At func name
[ "${i%_*}" == "_${0##*/}" -a "$j" == ")" ] && {
# Left aligned at 15 char
printf "%-15s%s\n" ${i##*_} "$k";
# Clear var
unset k
};
done < "$0"; # Scan this script
fi
}
# Cache exit
trap '_func_err $? $LINENO $BASH_LINENO $BASH_COMMAND ${FUNCNAME[@]}' EXIT
# # # # # # # # # # # # # # # # # # # # # # # # #
# Framework #
#################################################
# Test if help
[[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]] && {
_func_annotation | sort;
exit 0
} || [[ "$2" == "-h" || "$2" == "--help" ]] && {
# Test if help
_func_annotation $1 || printf "\033[31mError: No function found \033[0m\n" >&2;
exit $?
};
# $*, "$*", $@ can not keep $#, only "$@" can save native structural
# main
_${0##*/}_"$@"
# hdiutil attach *.dmg
# hdiutil detach *.dmg
# sudo bless --folder=/Volumes/BOOT --file=/Volumes/BOOT/EFI/BOOT/BOOTX64.efi --setBoot --lgacy
# sudo asr restore -source /Volumes/OS\ X\ Install\ ESD/BaseSystem.dmg -target /Volumes/Untitled -erase -format HFS+
# diskutil rename "$1" "RHD"
# touch .metadata_never_index
# mkdir com.apple.recovery.boot
# BaseSystem.chunklist
# boot.efi
# BaseSystem.dmg
# com.apple.Boot.plist
# .disk_label
# PlatformSupport.plist
# kernelcache
# .disk_label_2x
# SystemVersion.plist
# Erasing Disk: 0%... 10%... 20%... 30%...100%...
# Copying installer files to disk...
# Copy complete.
# Making disk bootable...
# Copying boot files...
# Copy complete.
# Done.
# .Trashes
# .fseventsd
# .IABootFiles
# Install OS X Yosemite.app
# .IABootFilesSystemVersion.plist
# Library
# .IAPhysicalMedia
# System
# .Spotlight-V100
# usr
# ./System/Library/CoreServices/boot.efi
# ./usr/standalone/i386/boot.efi
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。