-
Notifications
You must be signed in to change notification settings - Fork 0
/
maclinux.txt
438 lines (389 loc) · 25 KB
/
maclinux.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# -*- mode: shell-script -*-
# Script to make the Mac more Linux-like
# Version 1.64 (c) Silas S. Brown 2012-24.
# Tested in zsh on macOS 11.4 through 14.6,
# 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: 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/Golang:
export PATH=/usr/local/go/bin:$HOME/go/bin:/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 "$HOME"/.local/bin; do [ -e "$N" ] && export PATH="$PATH:$N"; done # for pip and pipx installing packages as user
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
pidof () (pgrep "^-*$@"'$')
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 airport && [ -e System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport ]; then
airport () { /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport "$@" ; }
export -f airport >/dev/null
fi
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 [ $((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" >&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
if ! /usr/bin/which -s jq && [ $(python --version 2>&1|sed -e 's/.* //' -e 's/\.//' -e 's/\..*//') -ge 26 ]; then jq () { python -m json.tool "$@" ; } ; export -f jq >/dev/null; fi
if ! /usr/bin/which -s factor && [ -e /opt/local/bin/gfactor ] ; then factor () { gfactor "$@" ; } ; export -f factor >/dev/null; fi # MacPorts coreutils
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
from distutils.spawn import find_executable
os.chdir("/usr/bin") # because at least some versions of distutils.spawn assume that PATH contains .
def orApp(c):
if not find_executable(c):
return c
elif not find_executable(c+"-app"): return c+"-app"
def getF(Command,App):
if not Command: return ""
elif "." in Command or "-" in Command:
return "alias \""+Command+"\"=\"open -W -a \\\""+App+"\\\"\""
else: return Command+" () { open -W -a \""+App+"\" \"$@\" ; } ; export -f "+Command+" >/dev/null"
for App in sys.argv[1:]:
Commands=[re.sub("[^a-z0-9._-]","",re.sub(".*/","",App)[:-4].replace(" ","-").lower())]
if Commands[0].startswith("microsoft-"): Commands.append(Commands[0].replace("microsoft-",""))
elif Commands[0]=="chmox" and not find_executable("kchmviewer"): Commands.append("kchmviewer") # probably easier to auto-complete, as chmox will suggest chmod also
elif Commands[0] in ["adobe-reader","adobe-acrobat-reader-dc","adobe-acrobat-reader"] and not find_executable("acroread"): Commands.append("acroread")
for Command in Commands: print (getF(orApp(Command),App))' >> $T
. $T ; rm $T ; unset T; }
else DefineApps () { false ; }; fi
DefineApps /Applications /System/Applications /System/Library/CoreServices/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"; DefineApps "$(declare -f xcode|grep -i '^\s*open.*/Xcode.app'|head -1|sed -e 's/[^"]*"//' -e 's/".*//')/Contents/Developer/Applications"; fi #'# (might find iphone-simulator etc there)
unset DefineApps
if [ -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
if [ -e /Applications/LibreOffice.app/Contents/MacOS/soffice ]; then
# for command-line conversions
soffice () { /Applications/LibreOffice.app/Contents/MacOS/soffice "$@" ; } ; export -f soffice >/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 /usr/libexec/java_home ] && ! [ "$JAVA_HOME" ] ; then export JAVA_HOME=$(/usr/libexec/java_home); 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 &&
[ -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 &&
[ -e "$sshfs_Path" ]; then
sshfs () { "$sshfs_Path" "$@" ; }
export -f sshfs >/dev/null
else unset sshfs_Path
fi
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"
# Can still set it from command line IF it's a multi-output device, NOT if it's an aggregate device (splitting stereo channels to separate Bluetooth feeds etc)
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 () { if [ ! "$SSH_CLIENT" ]; then [ ! "$(jobs -s)" ] && ( ( sleep 0.5 && osascript -e "tell application \"Finder\" to shut down") & ) ; exit ; else sudo shutdown -h now; fi ; }
# (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 [ -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 [ "$(hostname -s)" = mac ] || [ "$(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 [ -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 [ -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 ; }