WebCheck http://ssb22.user.srcf.net/setup/webcheck.html and ImapFix http://ssb22.user.srcf.net/setup/imapfix.html and MacLinux http://ssb22.user.srcf.net/setup/mac.html#maclinux
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
416 lines
24 KiB
416 lines
24 KiB
# -*- mode: shell-script -*- |
|
# Script to make the Mac more Linux-like |
|
# Version 1.592 (c) Silas S. Brown 2012-22. |
|
|
|
# Tested in zsh on macOS 11.4 through 12.2, |
|
# and in bash on Mac OS X 10.7 through 10.14. |
|
|
|
# This script can go in your ~/.zshrc (10.15+) |
|
# or ~/.bashrc and/or ~/.bash_profile (older Macs) |
|
# for example: |
|
# curl http://ssb22.user.srcf.net/setup/maclinux.txt >> ~/.bash_profile |
|
# or if you prefer you can keep it in a separate file |
|
# and source it from your startup files |
|
# (put "source ~/.maclinux" into .zshrc or .bashrc) |
|
|
|
# You might wish to also put it in BASH_ENV to ensure all |
|
# commands are copied to subshells, although commands without |
|
# hyphens and dots should be copied over anyway. |
|
|
|
# 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. |
|
|
|
# If you want to compare this code to old versions, the old |
|
# versions are being kept in the E-GuideDog SVN repository at |
|
# http://svn.code.sf.net/p/e-guidedog/code/ssb22/setup |
|
# and on GitHub at https://github.com/ssb22/web-imap-etc |
|
# and on GitLab at https://gitlab.com/ssb22/web-imap-etc |
|
# and on Bitbucket https://bitbucket.org/ssb22/web-imap-etc |
|
# and at https://gitlab.developers.cam.ac.uk/ssb22/web-imap-etc |
|
# and in China: git clone https://gitee.com/ssb22/web-imap-etc |
|
# although some early ones are missing. |
|
|
|
if [ -d /Volumes ] && [ "$(uname -s)" = Darwin ]; then |
|
# we're on a Mac |
|
|
|
# if in bash, avoid recursion: |
|
export __OldBashEnv="$BASH_ENV" ; unset BASH_ENV |
|
|
|
# Check SMART status of primary hard disk: |
|
diskutil info disk0|grep SMART|grep -v 'Status:[^A-z]*Verified$' && echo "Hard disk failing: backup NOW" && echo |
|
|
|
# Support installations of HomeBrew/MacTex/MacPorts/Fink: |
|
export PATH=/usr/texbin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/local/sbin:$PATH:/usr/local/opt/coreutils/libexec/gnubin |
|
# (gnubin (from coreutils package) comes last so Mac versions take priority, just in case; coreutils has some commands not otherwise available e.g. factor, md5sum) |
|
export MANPATH=$MANPATH:/usr/local/opt/coreutils/libexec/gnuman |
|
[ ! "$ZSH_NAME" ] && [ -e /sw/bin/init.sh ] && . /sw/bin/init.sh |
|
|
|
for N in "$HOME"/Library/Python/*/bin; do [ -e "$N" ] && export PATH="$PATH:$N"; done # for pip install --user (without --user it's /usr/local/bin) |
|
|
|
if [ ! "$ZSH_NAME" ] && /usr/bin/which -s brew; then |
|
# don't need any of our aliases when running HomeBrew scripts & it's quicker to bypass this file when doing so |
|
brew () { BASH_ENV= $(/usr/bin/which brew) "$@" ; } ; export -f brew |
|
fi |
|
|
|
if ! /usr/bin/which -s wget; then |
|
# Set wget to curl with appropriate options. Useful |
|
# if you're in the habit of typing "wget". Note that |
|
# it is not real wget however and it won't recognise |
|
# wget options like -c. |
|
wget () { curl -L --remote-name-all --compressed "$@" ; } |
|
# for older curl: alias wget="curl -OL" |
|
export -f wget >/dev/null |
|
fi |
|
|
|
if ! /usr/bin/which -s watch; then |
|
# primitive emulation of the "watch" command |
|
watch () (while true; do clear; date; echo "$@"; echo; "$@"; sleep 2; done) |
|
export -f watch >/dev/null |
|
fi |
|
|
|
if ! /usr/bin/which -s pidof; then |
|
# primitive emulation of the "pidof" command |
|
pidof () (ps axwww|fgrep "$@"|fgrep -v "fgrep $@"|sed -e 's/^ *//' -e 's/ .*//') |
|
export -f pidof >/dev/null |
|
fi |
|
|
|
top () { /usr/bin/top -stats $(if /usr/bin/top -l 1 -s 0 -stats mem >/dev/null 2>/dev/null; then echo pid,cpu,mem,uid,command; else echo pid,vsize,cpu,rsize,uid,command; fi) -o cpu $@ ; } |
|
# 11.x: -r with 'vsize' works but takes more CPU |
|
# 10.7: 'vsize' works w/out -r |
|
# 'state' works but takes more columns |
|
export -f top >/dev/null |
|
alias netstat-tl="lsof -iTCP -sTCP:LISTEN" |
|
alias netstat-t="lsof -iTCP -sTCP:ESTABLISHED" |
|
|
|
if ! /usr/bin/which -s free; then |
|
free () { top -l 1 -s 0 | grep -m 1 PhysMem ; } |
|
export -f free >/dev/null |
|
fi |
|
alias do-i-need-more-ram='if test $((vm_stat|grep "^Page[io]"|sed -e "s/.*://" -e "s/\.$//";echo 1;echo +;echo /;echo p)|(dc 2>/dev/null || echo 11)) -lt 10; then echo Maybe; else echo Probably not; fi' # 'maybe' if page outs are over 10% of page ins; +1 to avoid any possible division by zero if there have been no pageouts |
|
alias battery-status='pmset -g batt' # for MacBook laptops |
|
|
|
# Note: Anything with a hyphen in it must be an alias, not a |
|
# function (or at least not exported), or /bin/sh won't like |
|
# it and commands like "man" will fail. Hence the above |
|
# comment about BASH_ENV. |
|
|
|
# Define the /Applications as "open -a" commands so you |
|
# can type for example "libreoffice", "gimp", |
|
# "audacity" etc with a relative pathname and Mac open |
|
# will take care of translating it into an absolute |
|
# pathname and opening the appropriate Mac app with it. |
|
# Spaces are turned into hyphens, e.g. for google-chrome. |
|
# If a command already exists, we will append -app to it |
|
# (unless command-app already exists as well), for example |
|
# Emacs.app will become emacs-app if there's already emacs. |
|
# The version below unfortunately requires a temp file, |
|
# but it's usually faster than repeated calls to sed as in |
|
# previous versions of this script (1.38 and below). |
|
# (Bash can't source a /dev/fd from <(...), piping to a |
|
# source /dev/stdin invokes a subshell so it loses the |
|
# functions; no /dev/shm on Mac, so we have to use /tmp) |
|
# (see also comments around make-ramdisk function below). |
|
# TODO: if we must write to /tmp, can we keep it cached |
|
# so that new tabs in the Terminal window don't need to do |
|
# a disk write? (e.g. by putting whole script in an 'if' |
|
# clause which also does echo commands to declare the |
|
# functions, or cache the o/p of "declare" and somehow |
|
# remove what we didn't add), but how to check the age of |
|
# the cache? -newer /Applications? with timeout? |
|
# just make an 'update-functions' cmd for use when wanted? |
|
if [ -e /usr/bin/python3 ] ; then export DefineAppsPython=/usr/bin/python3 |
|
elif [ -e /usr/bin/python2 ] ; then export DefineAppsPython=/usr/bin/python2 |
|
else echo "maclinux cannot find system Python: most of our application shortcuts will NOT be defined" 1>&2; fi # TODO: search path for a user-installed Python? |
|
if ! /usr/bin/which -s python2 && /usr/bin/which -s python2.7; then python2 () { python2.7 "$@" ; } ; export -f python2 >/dev/null; fi # e.g. MacPorts on macOS 12.3 (no system python2) |
|
if [ "$DefineAppsPython" ]; then |
|
if ! /usr/bin/which -s python; then python () { "$DefineAppsPython" "$@" ; } ; export -f python >/dev/null; fi |
|
DefineApps () { export T=$(mktemp /tmp/$PPID''XXXXXX) ; find "$@" '(' -type d -or -type l ')' -name '*.app' -prune -print0 2>/dev/null | xargs -0 "$DefineAppsPython" -c 'import os,sys,re,distutils.spawn;os.chdir("/usr/bin")'$'\n''def orApp(c):'$'\n'' if not distutils.spawn.find_executable(c): return c'$'\n'' elif not distutils.spawn.find_executable(c+"-app"): return c+"-app"'$'\n\n''def getF(Command):'$'\n'' if "." in Command or "-" in Command: return lambda App: "alias \""+Command+"\"=\"open -W -a \\\""+App+"\\\"\""'$'\n'' else: return lambda App:Command+" () { open -W -a \""+App+"\" \"$@\" ; } ; export -f "+Command+" >/dev/null"'$'\n\n''print ("\n".join((lambda Command:getF(orApp(Command))(App))(Command=re.sub("[^a-z0-9._-]","",re.sub(".*/","",App)[:-4].replace(" ","-").lower())) for App in sys.argv[1:]))' >> $T ; . $T ; rm $T ; unset T; } # (the chdir to /usr/bin is because at least some versions of distutils.spawn assume that PATH contains . even when it doesn't) |
|
else DefineApps () { false ; }; fi |
|
DefineApps /Applications /System/Applications /usr/local/Cellar/emacs |
|
if declare -f xcode >/dev/null; then DefineApps "$(declare -f xcode|grep -i '^\s*open.*/Xcode.app'|head -1|sed -e 's/[^"]*"//' -e 's/".*//')/Contents/Applications"; fi #'# (might find iphone-simulator etc there) |
|
unset DefineApps |
|
|
|
if test -e /Applications/MacPorts/VLC.app/Contents/MacOS/VLC; then |
|
# override the above "open": might need its command line |
|
# (but not everything listed by -H really works) |
|
vlc () { /Applications/MacPorts/VLC.app/Contents/MacOS/VLC "$@" ; } ; export -f vlc >/dev/null |
|
fi |
|
|
|
# One slight annoyance is if you use some Macs that |
|
# have bbedit installed but others that just have |
|
# TextWrangler. Let's function-ify those edit commands: |
|
if /usr/bin/which -s bbedit; then |
|
edit () { bbedit "$@" ; } |
|
export -f edit >/dev/null |
|
elif /usr/bin/which -s edit; then |
|
bbedit () { edit "$@" ; } |
|
export -f bbedit >/dev/null |
|
else |
|
edit () { open -e "$@" ; } |
|
export -f edit >/dev/null # and leave bbedit undefined |
|
fi |
|
|
|
if [ -e /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/*/jsc ] ; then |
|
# command-line Javascript interpreter not in default PATH: might as well make this available |
|
jsc () { /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/*/jsc "$@" ; } |
|
if ! /usr/bin/which -s node; then |
|
# might as well alias it, in case you're in the |
|
# habit of typing "node" rather than "jsc" (it's |
|
# not the same, but near enough for simple tests) |
|
node () { jsc "$@" ; } |
|
export -f node >/dev/null |
|
fi |
|
fi |
|
|
|
# Ditto for mixed Mac/Linux environments where you |
|
# can type "jmacs" on the Linux terminal to get a |
|
# quick emacs-like editor: |
|
if ! /usr/bin/which -s jmacs; then |
|
if /usr/bin/which -s emacs; then |
|
jmacs () { emacs -q "$@" ; } ; export -f jmacs >/dev/null |
|
else # emacs not present in macOS 11, but we might have it as an application: |
|
if declare -f emacs >/dev/null; then |
|
jmacs () { Emacs=$(declare -f emacs|grep -i '^\s*open.*/Emacs.app'|head -1|sed -e 's/[^"]*"//' -e 's/".*//')/Contents/MacOS/Emacs; if [ ! "$1" ]; then $Emacs -q -nw --eval '(switch-to-buffer "*scratch*")'; else $Emacs -q -nw "$@"; fi ; } ; export -f jmacs >/dev/null |
|
elif declare -f aquamacs >/dev/null; then # TODO: not tested |
|
jmacs () { $(declare -f emacs|grep -i '^\s*open.*/Aquamacs.app'|head -1|sed -e 's/[^"]*"//' -e 's/".*//')/Contents/MacOS/Aquamacs -q -nw "$@" ; } ; export -f jmacs >/dev/null |
|
fi |
|
fi |
|
fi |
|
|
|
# and make sure you can type "play" to play sound files |
|
if ! /usr/bin/which -s play; then |
|
play () { afplay "$@" ; } ; export -f play >/dev/null ; fi |
|
|
|
# and "umount" to eject auto-mounted USB sticks etc: |
|
umount () { diskutil umount "$@" ; } ; export -f umount >/dev/null |
|
eject () { drutil eject ; } ; export -f eject >/dev/null # for CDs |
|
|
|
# and the general "web browser" command used by some |
|
# scripts in Debian etc |
|
alias x-www-browser=open # should recognise a URL |
|
alias gnome-open=open |
|
|
|
# If you have installed Macfusion (which requires MacFUSE |
|
# or the MacFUSE compatibility layer of OSXFUSE) then |
|
# make its curlftpfs and sshfs commands available. Note |
|
# however that curlftpfs can be unreliable, e.g. some |
|
# versions do not properly truncate files when you try to |
|
# overwrite with less data, plus large transfers can break, |
|
# so some situations might be better using .netrc or TRAMP. |
|
# If you do use ftpfs and the server is running it via |
|
# inetd then you might need to increase the connections/min |
|
# allowed in inetd.conf, e.g. "ftp stream tcp nowait.32767" |
|
if declare -f macfusion >/dev/null; then |
|
export MF_Path="$(declare -f macfusion|grep -i '^\s*open .*/Macfusion.app'|head -1|sed -e 's/[^"]*"//' -e 's/".*//')" #' # (comment for some versions of Emacs syntax highlighting) |
|
export sshfs_Path="$MF_Path/Contents/PlugIns/sshfs.mfplugin/Contents/Resources/sshfs-static" |
|
export curlftpfs_Path="$MF_Path/Contents/PlugIns/ftpfs.mfplugin/Contents/Resources/curlftpfs_static_mg" |
|
unset MF_Path |
|
if ! /usr/bin/which -s curlftpfs && |
|
test -e "$curlftpfs_Path"; then |
|
curlftpfs () { "$curlftpfs_Path" -o uid="$(id -u)" "$@" ; } |
|
ftpfs () { curlftpfs "$@" ; } # might as well |
|
export -f curlftpfs ftpfs >/dev/null |
|
else unset curlftpfs_Path |
|
fi |
|
if ! /usr/bin/which -s sshfs && |
|
test -e "$sshfs_Path"; then |
|
sshfs () { "$sshfs_Path" "$@" ; } |
|
export -f sshfs >/dev/null |
|
else unset sshfs_Path |
|
fi |
|
fi |
|
|
|
if declare -f chmox >/dev/null && ! /usr/bin/which -s kchmviewer; then |
|
kchmviewer () { chmox "$@" ; } ; export -f kchmviewer >/dev/null |
|
# kchmviewer is probably easier to auto-complete, as |
|
# chmox will suggest chmod also. |
|
# Intel binaries are included in chmox 0.4+ |
|
fi |
|
|
|
if alias adobe-reader 2>/dev/null >/dev/null && ! /usr/bin/which -s acroread; then |
|
acroread () { open -W -a "$(alias adobe-reader|sed -e 's/[^"]*"//' -e 's/".*//')" "$@" ; } # must define it this way, not just by calling adobe-reader within the function, because our aliases might not be available in a subshell |
|
export -f acroread >/dev/null |
|
elif alias adobe-acrobat-reader-dc 2>/dev/null >/dev/null && ! /usr/bin/which -s acroread; then |
|
acroread () { open -W -a "$(alias adobe-acrobat-reader-dc|sed -e 's/[^"]*"//' -e 's/".*//')" "$@" ; } |
|
export -f acroread >/dev/null |
|
fi |
|
|
|
# If you have installed fuse-ext2 then might as well set |
|
# its mke2fs (although usually you'd use fuse-ext2 or |
|
# mount -t fuse-ext2) |
|
if ! /usr/bin/which -s mke2fs && /usr/bin/which -s fuse-ext2.mke2fs; then |
|
mke2fs () { fuse-ext2.mke2fs "$@" ; } |
|
e2fsmount () { fuse-ext2 "$@" ; } |
|
export -f mke2fs e2fsmount >/dev/null |
|
fi |
|
|
|
ulimit -n 1024 # allow programs to have more open files |
|
|
|
# Setting the volume from the command line (this |
|
# doesn't exactly emulate the Linux commands on various |
|
# distributions but at least it's a start) - |
|
volume () { |
|
if [ ! "$1" ]; then |
|
# if no argument, print current percentage |
|
V=$(osascript -e "output volume of (get volume settings)") |
|
if [ "$V" = "missing value" ]; then |
|
echo "Cannot read current volume" |
|
echo "This can happen if a multi-output device has been set in audio-midi-setup" |
|
echo "(e.g. to copy computer's sound to QuickTime's recorder via BlackHole)" # (or SoundFlower on older Macs?) |
|
echo " - audio-midi-setup must be used to read volume" |
|
echo "(can still set it from command line)" # (at least it could when I tested it) |
|
else echo "$V"; fi |
|
else osascript -e "set volume output volume $1"; fi } |
|
# older Macs just had "set volume" with a number 0 to 7 |
|
export -f volume >/dev/null |
|
|
|
# might as well have some iTunes command-line access too - |
|
# here's a function that plays a track whose name contains |
|
# whatever string you pass to the function: |
|
play-track () { osascript -e "tell application \"iTunes\" to play (get item 1 of (get every track of current playlist where name contains \"$*\"))"; } |
|
alias list-track-names="osascript -e \"set AppleScript's text item delimiters to \\\"@@@\\\"\" -e \"tell application \\\"iTunes\\\" to get name of (every track of current playlist) as string\"|sed -e $'s/@@@/\\\\\\n/g'|less -S" |
|
alias next-track='osascript -e "tell application \"iTunes\" to next track"' |
|
alias previous-track='osascript -e "tell application \"iTunes\" to previous track"' |
|
pause () { osascript -e "tell application \"iTunes\" to pause" ; } # resume from GUI for now (right-click on the dock) |
|
stop () { osascript -e "tell application \"iTunes\" to stop" ; } |
|
export -f pause stop >/dev/null |
|
|
|
# we can also do the following without sudo, as long as a desktop session is running: |
|
halt () { [ ! "$(jobs -s)" ] && ( ( sleep 0.5 && osascript -e "tell application \"Finder\" to shut down") & ) ; exit ; } |
|
# (if the "exit" warns about stopped jobs, we won't do the shutdown) |
|
poweroff () { halt ; } |
|
reboot () { [ ! "$(jobs -s)" ] && ( ( sleep 0.5 && osascript -e "tell application \"Finder\" to restart") & ) ; exit ; } |
|
logout () { [ ! "$(jobs -s)" ] && ( ( sleep 0.5 && osascript -e "tell application \"System Events\" to log out") & ) ; exit ; } |
|
sleepnow () { if ! pmset -g assertions|grep PreventSystemSleep|grep -v '^\s*PreventSystemSleep\s*0$'; then (sleep 0.5; pmset sleepnow) & exit; else false; fi ; } |
|
alias suspend-mac=sleepnow |
|
export -f halt poweroff reboot logout sleepnow >/dev/null |
|
# (the "exit"s at the end of the above are so the terminal doesn't stop it with "are you sure", unless there are other terminal sessions) |
|
|
|
# Spotlight is required by app-store, e.g. for XCode updates (otherwise can get misleading error messages about account sign-in). But you might want Spotlight disabled at other times (especially when accessing removable media). |
|
alias spotlight-disable="sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist" |
|
alias spotlight-enable="sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.metadata.mds.plist" |
|
|
|
updatedb () { sudo /usr/libexec/locate.updatedb ; } |
|
export -f updatedb >/dev/null |
|
# note that updatedb does not look in any user directories |
|
# that are chmod'd to 700 (user only) - be sure to chmod |
|
# a+rx any dirs you want it to scan |
|
|
|
# Here's a function to install arbitrary commands to run at desktop login |
|
# Notes: (1) PATH might be incomplete, (2) this maclinux won't have been executed (unless you source it in the script), |
|
# (3) if the script starts any background processes, it MUST do a "wait" before finishing if you don't want launchctl to terminate its background processes |
|
_install_login_command () { |
|
if ! [ -e "/$1" ]; then echo "Syntax: install-login-command executable-full-path"; echo "(see comments in maclinux for caveats)"; return; fi |
|
mkdir -p "$HOME/Library/LaunchAgents" |
|
L="$(echo "$1"|sed -e 's,.*/,,')" |
|
if [ -e "$HOME/Library/LaunchAgents/$L.plist" ] || [ ! "$L" ] || ! touch "$HOME/Library/LaunchAgents/$L.plist" 2>/dev/null; then |
|
# can't use executable name as plist name (exists or can't create), so make a generic one |
|
C=0; while test -e "$HOME/Library/LaunchAgents/loginscript$C.plist"; do C=$[$C+1]; done; L=loginscript$C |
|
fi |
|
F="$HOME/Library/LaunchAgents/$L.plist"; (echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";echo "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"><plist version=\"1.0\"><dict><key>Label</key><string>$L</string><key>Program</key><string>$1</string><key>RunAtLoad</key><true/></dict></plist>") > "$F" |
|
launchctl load "$F" |
|
echo "Installed to $F" # (use "launchctl unload" and "rm" to uninstall) |
|
echo "To test now, do: launchctl start $L"; |
|
echo "(errors to /var/log/system.log)"; |
|
} |
|
# (change $HOME/Library/LaunchAgents to /Library/LaunchAgents to run on boot instead of login, but crontab @reboot can do that) |
|
alias install-login-command=_install_login_command |
|
|
|
_make_ramdisk () { |
|
case "$1" in |
|
"") echo "Syntax: make-ramdisk mountpoint size" |
|
# (or size mountpoint : will auto-reverse) |
|
echo "(512-byte blocks, min 1024 for 512k," |
|
echo "can specify as M or G instead)" |
|
false ;; |
|
[1-9]*) case "$2" in [1-9]*) echo "Mountpoint must not start with a number"; false ;; *) _make_ramdisk "$2" "$1" ;; esac ;; |
|
*) |
|
case "$2" in |
|
[1-9]*[gG]) _make_ramdisk "$1" "$[${2%[gG]}*2097152]" ;; |
|
[1-9]*[mM]) _make_ramdisk "$1" "$[${2%[mM]}*2048]" ;; |
|
*) mkdir "$1" && mount -t hfs "$(echo "$(newfs_hfs $(hdid -nomount "ram://$2"))"|sed -e 's,[^/]*/,/,' -e 's/ .*//' -e 's,/rdisk,/disk,')" "$1" ;; |
|
esac ;; |
|
esac ; } |
|
# (10.5+ can also do e.g. diskutil erasevolume HFS+ "maclinux-RAMdisk" $(hdiutil attach -nomount ram://1024) for /Volumes/maclinux-RAMdisk) |
|
alias make-ramdisk=_make_ramdisk |
|
_drop_ramdisk () { D="$(mount|grep "$(echo "$1"|sed -e 's,/$,,') "|sed -e 's/ .*//')" ; /sbin/umount "$1" ; hdiutil detach "$D" ; rmdir "$1" ; } |
|
alias drop-ramdisk=_drop_ramdisk |
|
export -f _make_ramdisk _drop_ramdisk >/dev/null # so can use from scripts (useful especially if have upgraded HDD to SSD and worried about excessive writes by script temp files) |
|
|
|
# NOTE: for making HFS+ disk images that will interoperate |
|
# with Linux, it's really best to do this IN LINUX (use dd |
|
# and then use mkfs.hfs from hfsprogs), rather than on the |
|
# Mac. That way it's less likely you'll end up with a dmg |
|
# that the Linux kernel refuses to mount for some reason. |
|
|
|
function xmanpage() { open x-man-page://$@ ; echo "To change appearance: Terminal / Preferences / Settings / Man page / (Text,Window)" ; } |
|
export -f xmanpage >/dev/null |
|
if ! /usr/bin/which -s xman; then xman () { xmanpage "$@" ; } ; export -f xman >/dev/null; fi # (if X11 is present then xman should be installed, but it may fail to read all manpage sections and UTF-8 won't display) |
|
function psmanpage() { man -t "$@" | open -f -a Preview ; } # will need Invert to change the colours of that |
|
export -f psmanpage >/dev/null |
|
alias man-terminal=xmanpage # for auto-complete "man" |
|
alias man-ps=psmanpage |
|
|
|
# Mac's multiline editing doesn't always work well with ANSI codes, even when \[..\] delimiters are used |
|
if [ ! "$SSH_CLIENT" ]; then |
|
# simpler prompt for a local Mac (hostname can be a bit long) |
|
[ "$ZSH_NAME" ] && PS1='mac:%~%# ' || PS1='mac:\w\$ ' |
|
elif test "$(hostname -s)" = mac || test "$(hostname -s)" = unknown; then |
|
# if hostname has been SET to mac, better make it different |
|
# to distinguish between a local one and one over SSH |
|
[ "$ZSH_NAME" ] && PS1='mac.ssh:%~%# ' || PS1='mac.ssh:\w\$ ' |
|
case "$TERM" in xterm*) echo -n $'\033]0;mac ssh\007' ;; esac |
|
else |
|
[ "$ZSH_NAME" ] && PS1='%m:%~%# ' || PS1='\h:\w\$ ' |
|
case "$TERM" in xterm*) echo -n $'\033]0;'"$(hostname -s)"$'\007' ;; esac |
|
fi |
|
case "$TERM" in xterm*) [ "$ZSH_NAME" ] && PS1=$'%{\e[1;37;40m%}'"$PS1"$'%{\e[1;33;40m%}' || PS1='\[\e[1;37;40m\]'"$PS1"'\[\e[1;33;40m\]' ;; esac |
|
|
|
export BASH_ENV="$__OldBashEnv" |
|
if [ "$ZSH_NAME" ]; then |
|
unsetopt hup check_running_jobs bad_pattern no_match # as bash |
|
setopt -k # allow comments even in interactive (as bash does) |
|
fi |
|
|
|
else # not on a Mac |
|
if [ "$COLUMNS" ] && [ $COLUMNS -le 50 ] && wget --version 2>/dev/null|head -1|grep "Wget 1.17" >/dev/null; then alias wget="echo 'Doing wget -q to work around Debian bug #823891';wget -q" # non-Mac, but that bug affects the version of wget shipped with Ubuntu 16.04 LTS so I put this in for the Cambridge MCS remote GNU/Linux machines at the time |
|
fi |
|
if [ -e /usr/bin/amixer ] ; then |
|
# for consistency, re-define our "volume" command for amixer on non-Mac |
|
volume () { |
|
if [ ! "$1" ]; then amixer sget Master |
|
else amixer sset Master "$1%"; fi } |
|
export -f volume >/dev/null |
|
if [ -n "$SSH_CLIENT" ]; then export DBUS_SESSION_BUS_ADDRESS=$(cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -m 1 DBUS_SESSION_BUS_ADDRESS | cut -d = -f2-); if ! [ -n "$DBUS_SESSION_BUS_ADDRESS" ]; then unset DBUS_SESSION_BUS_ADDRESS ; fi; fi |
|
fi |
|
fi # end of "not on a Mac" block |
|
# (so you can put all this into a .bashrc that will |
|
# get sourced from either Mac or Linux machines) |
|
|
|
which unix2dos >/dev/null 2>/dev/null || alias unix2dos="perl -i -p -e 's|[\r\n]+|\r\n|g'" # (outside Mac section because might also be useful on Linux if unix2dos is missing and you need to send a .txt file to someone who has only Windows Notepad) |
|
|
|
# "Bonus" command (not just Mac but may be useful on some |
|
# Linux systems) - a simple 'catdocx' (like catdoc if it's |
|
# installed, but for docx files - just extracts text |
|
# between the XML markup). catdocx_utf8 outputs UTF-8; |
|
# catdocx_cp1252 outputs "Windows 1252" as used on old |
|
# Psion PDAs etc. |
|
catdocx_utf8 () { while [ "$1" ]; do unzip -Cp "$1" word/[dfe]*[ts].xml; shift; done|perl -p -e 's/<w:p(\s[^>]*)?>/\n/g;s/<[^>]*>//g;s/ */ /g;s/</</g;s/>/>/g'|grep -v '^\s*$' ; } # (want to unzip document.xml, endnotes.xml and footnotes.xml but not emit warnings if missing and not match fontTable etc, hence the awkward file specification; perl rather than sed so as to avoid BSD sed / gsed differences re \n in replacement etc) |
|
catdocx_cp1252 () { catdocx_utf8 "$@" | iconv -c -f UTF8 -t CP1252//TRANSLIT ; } # --unicode-subst="[U+%04X]" instead of -c would be nice, but it's not available on all versions of iconv |
|
|
|
# Bonus command 2: cat a load of text files into a |
|
# self-extracting shell script (for email or whatever) |
|
# (must o/p to a file; i/p cannot incl dirs) |
|
shellarc () { Out="$1"; if test -e "$Out" ; then echo "Output file $Out exists; I'd rather not overwrite it" ; return; fi; echo "Writing $Out"; (echo '#!/bin/bash' ; while [ "$2" ]; do if echo "$2"|grep / >/dev/null; then echo mkdir -p '"'"$(echo "$2"|sed -e 's,/[^/]*$,,')"'"'; fi; C=0; while grep EOF$C "$2" >/dev/null; do C=$[C+1]; done ; echo "cat > \"$2\" <<\"EOF$C\"" ; cat $2 ; echo EOF$C ; shift; done) > "$Out" ; chmod +x "$Out" ; } |
|
|
|
# Bonus command 3: pdfmerge, on any machine with qpdf installed (to help with double-sided printing) |
|
which qpdf >/dev/null 2>/dev/null && pdfmerge () { if test -e merged.pdf; then rm -i merged.pdf; fi && qpdf --empty --pages $(for i in $@; do echo $i 1-z; done) -- merged.pdf && du -h merged.pdf ; }
|
|
|