├── .autosync ├── .bash_profile ├── .bashenv ├── .bashenv.d └── PS4 ├── .bashrc ├── .cfg-post.d ├── cron ├── netrc └── shell-env ├── .config └── ripgreprc ├── .cron.d └── 30-header ├── .dircolors ├── .inputrc ├── .lesskey ├── .log └── .gitkeep ├── .ns ├── .profile ├── .rsync-filter ├── .shared_env ├── .shared_env.d ├── 00-hostname ├── 00-ostype ├── 00-user └── 10-Perl ├── .shared_rc ├── .shared_rc.d ├── md5 ├── nvm ├── pnpm ├── ripgrep └── sx ├── .stow-local-ignore ├── .switch_shell ├── .url_handler.d ├── 00-local-files ├── 10-strip-quotes ├── 10-u-template ├── 14-notion-app-enhanced ├── 15-switch-workspace └── 20-adobe-acrobat ├── .zsh ├── accounts.d │ └── TEMPLATE ├── cx.d │ └── TEMPLATE ├── functions │ ├── _cf │ ├── _cleanzip │ ├── _eshade │ ├── _hostgroup │ ├── _lh │ ├── _mnx │ ├── _msoffice │ ├── _mx │ ├── _oocalc │ ├── _oodraw │ ├── _ooffice │ ├── _ooimpress │ ├── _oomath │ ├── _oowriter │ ├── _palm_PDBs │ ├── _plucker-install │ ├── _rd │ ├── _resolve_path │ ├── _ru │ ├── _save_xmodmap │ ├── _sc │ ├── _scoop │ ├── _scoop-install │ ├── _scvs │ ├── _service_shortcuts │ ├── _spa │ ├── _str │ ├── _up │ ├── _wh │ ├── _whenup │ ├── _wl │ ├── _z │ ├── autoload_test1 │ ├── autoload_test2 │ ├── autoload_test3 │ ├── autoload_test_all │ ├── ba │ ├── bx │ ├── check_hist_size │ ├── cleanzip │ ├── cvs │ ├── cvsls │ ├── cx │ ├── cxl │ ├── cxp │ ├── cxx │ ├── enable_nullglob │ ├── enable_wordsplit │ ├── etint │ ├── extglob │ ├── fext │ ├── find_hooks │ ├── fmbox │ ├── ftp │ ├── histmerge │ ├── imv │ ├── kill-region-or-backward-big-word │ ├── kill-region-or-backward-word │ ├── magic-backward-word │ ├── magic-forward-char │ ├── magic-forward-to-space │ ├── magic-forward-word │ ├── magic-kill-word │ ├── magic-space │ ├── mcd │ ├── ncftp │ ├── nullglob │ ├── only │ ├── oo │ ├── pdf │ ├── pmg │ ├── pmgrep │ ├── prompt_adam2 │ ├── run_hooks │ ├── sc │ ├── scvs │ ├── set_title │ ├── spa │ ├── srm │ ├── ster │ ├── str │ ├── switch_cvsroot │ ├── th │ ├── transpose-big-words │ ├── v1 │ ├── v2 │ ├── ve │ ├── vterm_printf │ ├── vx │ ├── wh │ ├── xt │ └── zrec └── users.d │ └── TEMPLATE ├── .zshenv ├── .zshrc ├── .zshrc.other-user ├── COPYING ├── README.md ├── bin ├── AC-online ├── AC-state ├── abs ├── active-since ├── age-of ├── age-track ├── alertme ├── atimeout ├── beep ├── bip ├── bping ├── bsplit ├── c3 ├── cg ├── clip ├── cm ├── colour-diff-output ├── count-dirents ├── cp-merge ├── crypt ├── csort ├── cy ├── dbm ├── dfh ├── dfl ├── dfll ├── diff-inodes ├── diff-less ├── div ├── dl ├── dts ├── du1 ├── du2 ├── dump-inodes ├── dumpenv ├── dutree ├── dwatch ├── edate ├── fbig ├── fds ├── fdst ├── feed ├── file-datestamp ├── find-wan-gateway ├── fs-monitor ├── fswap ├── ftrace ├── glob-to-re ├── grep-shortcuts ├── gse ├── gw-IP ├── gw-dev ├── gw-dev-IP ├── gw-devs ├── harden-ln ├── hex ├── host-has-prop ├── icmp-blocked ├── ifw ├── isup ├── jc ├── jcf ├── jcf2 ├── jcfu ├── jl ├── jlu ├── keepalive ├── lesspipe.sh ├── lh ├── lnav2 ├── lnave ├── lnavf ├── logseek ├── ls-sparse ├── lse ├── lsofp ├── lswap ├── mnp ├── mnt-image ├── mnt-initrd ├── mnt-isos ├── mnx ├── mp ├── multi-syphon ├── mv-merge ├── mvi ├── mx ├── newer ├── nm-current-connection ├── nm-current-connections ├── nmw ├── nmwc ├── nth ├── ntrace ├── open ├── ord ├── ox ├── pdf ├── penv ├── phup ├── pinggw ├── pingns ├── pingwan ├── protect ├── pst ├── pstt ├── quietrun ├── ra ├── ra.pats ├── ran ├── rc ├── rcg ├── rcslocks ├── resolver-domain ├── rj ├── rjd ├── rjr ├── rm-src-dups ├── root-zsh ├── rot13 ├── rotate ├── rpath ├── safe-pipe ├── service-commands ├── sfind ├── show-colours ├── shuffle ├── so ├── sort-bash-history ├── sort-by-filename ├── source-only ├── split-by-boot ├── syphon ├── tailfgrep ├── tf ├── tfs ├── tl ├── tre ├── trel ├── trim-lines ├── trim-whitespace ├── tty-colour-diff ├── udate ├── uidle ├── ujc ├── ujcf ├── ujcfu ├── ujcu ├── ujl ├── ujlu ├── umnt-initrd ├── un ├── unindent ├── unpack ├── up ├── up-since ├── url-handler ├── url_handler.sh ├── usc ├── usca ├── uuid ├── viz ├── waitpid ├── waitproc ├── watchdiff ├── wchan ├── wd ├── wdf ├── wget-monitor ├── whenup ├── wl ├── xauth-user ├── zdate └── zipseqs ├── doc └── ConfigHooks.org ├── lib ├── fs-trend.gnuplot ├── libhooks.sh ├── libhost.sh ├── liblogging.sh ├── libuid.sh └── perl5 │ ├── Sh.pm │ └── Sh.t └── t ├── .gitignore ├── Makefile ├── mv-merge └── mv-merge-test.vanilla │ ├── dst │ ├── a │ │ └── b │ │ │ ├── newer-in-src │ │ │ ├── older-in-src │ │ │ ├── only-dst │ │ │ └── same │ └── c │ │ ├── newer-in-src │ │ ├── older-in-src │ │ ├── only-dst │ │ └── same │ └── src │ ├── a │ └── b │ │ ├── newer-in-src │ │ ├── older-in-src │ │ ├── only-src │ │ └── same │ ├── c │ ├── newer-in-src │ ├── older-in-src │ ├── only-src │ └── same │ └── d ├── t0001-mv-merge.sh ├── test-lib-functions.sh └── test-lib.sh /.autosync: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspiers/shell-env/8a54c5e45ba72a42943dd30f9c713c6c7921837f/.autosync -------------------------------------------------------------------------------- /.bash_profile: -------------------------------------------------------------------------------- 1 | # Adam's .bash_profile 2 | # 3 | # for those shitty times when zsh isn't to hand 4 | # 5 | # $Id$ 6 | 7 | # .bash_profile is invoked in preference to .profile by interactive 8 | # login shells, and by non-interactive shells with the --login option. 9 | 10 | # Allow disabling of all meddling with the environment 11 | [ -n "$INHERIT_ENV" ] && return 0 12 | 13 | if [ -f ~/.bashrc ]; then 14 | # Get the normal interactive stuff from .bashrc 15 | . ~/.bashrc 16 | fi 17 | 18 | . $ZDOT_RUN_HOOKS .bash_profile.d 19 | 20 | -------------------------------------------------------------------------------- /.bashenv: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Adam's .bashenv 4 | # 5 | # to simulate .zshenv 6 | # 7 | # $Id$ 8 | 9 | # .bashenv is invoked by all interactive non-csh-style shells via 10 | # .profile, and hopefully all non-interactive shells too, but don't 11 | # bet on the latter; it depends on whether ENV or BASH_ENV were set, 12 | # and the version of bash. ~/.ssh/environment can set it if ssh is 13 | # involved. As a result, assume the lowest common denominator, e.g. 14 | # old ksh's don't even support ~ expansion, or 'source' (use '.' 15 | # instead). 16 | 17 | : .bashenv starts # for debugging with -x 18 | 19 | # Allow disabling of all meddling with the environment 20 | [ -n "$INHERIT_ENV" ] && return 0 21 | 22 | shell=bash 23 | 24 | [ -r ${ZDOTDIR:-$HOME}/.shared_env ] && . ${ZDOTDIR:-$HOME}/.shared_env 25 | 26 | sh_load_status .bashenv 27 | 28 | . $ZDOT_RUN_HOOKS .bashenv.d 29 | 30 | : .bashenv ends # for debugging with -x 31 | -------------------------------------------------------------------------------- /.bashenv.d/PS4: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # requires export BASH_ENV=~/.bashenv which will mean a performance hit, 4 | # so not worth doing in general 5 | 6 | PS4="+\${BASH_SOURCE/\$HOME/\~}@\${LINENO}(\${FUNCNAME[0]}): " 7 | -------------------------------------------------------------------------------- /.cfg-post.d/cron: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | confdir=.cron.d 4 | config=$HOME/.crontab 5 | 6 | source "$HOME/.shared_env" 7 | source "$HOME/lib/libhooks.sh" 8 | 9 | crontab -l > "$config" 10 | 11 | if ! rebuild_config "$config" "$confdir"; then 12 | echo "ERROR: failed to rebuild $config from $confdir" >&2 13 | exit 1 14 | fi 15 | 16 | if ( echo; cat "$config" ) | crontab -; then 17 | echo "Reinstalled user's crontab" 18 | else 19 | echo "WARNING: Failed to reinstall user's crontab" >&2 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /.cfg-post.d/netrc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | confdir=$HOME/.netrc.d 4 | config=$HOME/.netrc 5 | 6 | [ -d $confdir ] || mkdir -p $confdir 7 | 8 | source "$ZDOTDIR/lib/libhooks.sh" 9 | 10 | rebuild_config "$config" "${confdir#$HOME/}" 11 | 12 | chmod go-rwx -R $config $confdir 13 | -------------------------------------------------------------------------------- /.cfg-post.d/shell-env: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ~/bin/service-commands 4 | ~/bin/cm 5 | ~/bin/grep-shortcuts 6 | ( cd ~/bin; [ -e rjt ] || ln -sf rj rjt ) 7 | 8 | if which zsh >&/dev/null; then 9 | zsh -c zrec 10 | fi 11 | 12 | # Make sure synced with $LESSKEY in .shared_env 13 | if which lesskey >/dev/null 2>&1; then 14 | lesskey -o ~/.less 15 | fi 16 | 17 | ~/.cfg-post.d/cron 18 | 19 | mkdir -p ~/.run 20 | -------------------------------------------------------------------------------- /.config/ripgreprc: -------------------------------------------------------------------------------- 1 | --hidden 2 | -------------------------------------------------------------------------------- /.cron.d/30-header: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # %% Executable hook %% 4 | 5 | cat <&2 21 | return 1 22 | fi 23 | elif [ -n "$BASH_VERSION" ]; then 24 | current_shell=bash 25 | else 26 | case "$SHELL" in 27 | *bash) current_shell=bash ;; 28 | *zsh) current_shell=zsh ;; 29 | esac 30 | fi 31 | } 32 | 33 | find_me () { 34 | if [ -n "$1" ] && grep -q '# .ns - Nice Shell' "$1"; then 35 | me="$1" 36 | return 0 37 | fi 38 | 39 | if [ -n "${BASH_SOURCE[0]}" ]; then 40 | me="${BASH_SOURCE[0]}" 41 | else 42 | me="$0" 43 | fi 44 | case "$here" in 45 | -*) 46 | echo "Couldn't figure out where to look for .zshrc; please specify ZDOTDIR. Aborting." >&2 47 | return 1 48 | ;; 49 | esac 50 | return 0 51 | } 52 | 53 | find_zdotdir () { 54 | here="`dirname $me`" 55 | if ! [ -e $here/.zshrc ]; then 56 | echo "$here missing .zshrc, aborting." >&2 57 | return 1 58 | fi 59 | 60 | # Not sure why I bothered with this. 61 | # here="`$here/bin/shortcuts/abs $0`" 62 | # here="`dirname $here`" 63 | 64 | if ! [ -e $here/.zshrc ]; then 65 | echo "abs failed" 66 | return 1 67 | fi 68 | 69 | ZDOTDIR="$here" 70 | return 0 71 | } 72 | 73 | detect_current_shell 74 | 75 | # We have to intelligently guess where this file is. 76 | # When this file is sourced: 77 | # in sh/bash/ksh, $0 becomes the interpreter name (i.e. 'bash' etc.) 78 | # in zsh, $0 becomes the argument to source (i.e. this file) 79 | case "$current_shell" in 80 | bash) 81 | find_me || return $? 82 | ;; 83 | zsh) 84 | find_me "$0" || return $? 85 | ;; 86 | *) 87 | echo "FIXME: current_shell=$current_shell not yet supported" >&2 88 | return 1 89 | ;; 90 | esac 91 | 92 | if [ -z "$ZDOTDIR" ]; then 93 | find_zdotdir || return $? 94 | fi 95 | if [ -z "$ZDOTDIR" ]; then 96 | echo "BUG: find_zdotdir failed?!" >&2 97 | return 1 98 | fi 99 | export ZDOTDIR # but see caveat at EOF 100 | 101 | [ -z "$shared_env_loaded" ] && source "$ZDOTDIR/.shared_env" 102 | 103 | # Don't do anything with non-interactive shells. 104 | [ -z "$shell_interactive" ] && return 1 105 | 106 | if [ -n "$DEBUG_NS" ]; then 107 | set +x 108 | fi 109 | 110 | case "$current_shell" in 111 | bash) 112 | source "$ZDOTDIR/.bashenv" 113 | source "$ZDOTDIR/.bashrc" 114 | # Are you feeling lucky, punk? 115 | SHLVL=force_danger source "$ZDOTDIR/.switch_shell" "$@" 116 | ;; 117 | zsh) 118 | source "$ZDOTDIR/.zshenv" 119 | source "$ZDOTDIR/.zshrc" 120 | ;; 121 | *) 122 | source "$ZDOTDIR/.switch_shell" "$@" 123 | ;; 124 | esac 125 | 126 | # N.B. If this file was source'd via: 127 | # ZDOTDIR=/home/aspiers source /home/aspiers/.ns 128 | # or similar, as soon as the "source-ing" finishes, 129 | # for some reason ZDOTDIR vanishes. So better to 130 | # do an explicit export of ZDOTDIR at invocation time. 131 | # Dunno if this is a bug or feature. 132 | -------------------------------------------------------------------------------- /.profile: -------------------------------------------------------------------------------- 1 | # This is read when sh or ksh is invoked. 2 | 3 | # FIXME: .profile run but need to steal portable stuff from bashrc 4 | #. $HOME/.bashrc 5 | -------------------------------------------------------------------------------- /.rsync-filter: -------------------------------------------------------------------------------- 1 | - .cpan/build/ 2 | - .cpan/Metadata 3 | - .cpan/sources/ 4 | - .md5/ 5 | - *.zwc 6 | - *.elc 7 | - .emacs.backup/ 8 | - *.orig 9 | -------------------------------------------------------------------------------- /.shared_env.d/00-hostname: -------------------------------------------------------------------------------- 1 | # -*- mode: sh -*- 2 | 3 | : ${HOST:=${HOSTNAME:-`hostname`}} 4 | : ${HOSTNAME:=$HOST} 5 | 6 | # Let's not make this *too* sticky because dhcp might change the host 7 | #export HOST HOSTNAME 8 | -------------------------------------------------------------------------------- /.shared_env.d/00-ostype: -------------------------------------------------------------------------------- 1 | # -*- mode: sh -*- 2 | 3 | # Can come in handy too, if the shell sets it (bash and zsh do). 4 | export OSTYPE 5 | -------------------------------------------------------------------------------- /.shared_env.d/00-user: -------------------------------------------------------------------------------- 1 | # -*- mode: sh -*- 2 | 3 | # zsh sets USERNAME, GROUPS, and E?[UG]ID 4 | # bash only sets E?UID 5 | USER=${USERNAME:-`id -un`} 6 | : ${USERNAME:=$USER} 7 | export USER USERNAME 8 | -------------------------------------------------------------------------------- /.shared_env.d/10-Perl: -------------------------------------------------------------------------------- 1 | # -*- mode: sh -*- 2 | 3 | export PERL5LIB 4 | 5 | add_perl5lib_path () { 6 | new_path="$1" 7 | case "$PERL5LIB" in 8 | '') 9 | PERL5LIB=$new_path 10 | ;; 11 | 12 | $new_path|*:$new_path|$new_path:*|*:$new_path:*) 13 | : #echo "$newpaths already in \$PERL5LIB" 14 | ;; 15 | *) 16 | PERL5LIB=$new_path:$PERL5LIB 17 | ;; 18 | esac 19 | } 20 | 21 | for dir in $ZDOTDIRREVPATH; do 22 | add_perl5lib_path $dir/lib/perl5 23 | add_perl5lib_path $dir/lib/perl5/site_perl 24 | 25 | # # Use a cache to avoid invoking Perl during startup of every single 26 | # # shell (even non-interactive ones). 27 | # cachedir=$dir/.config/perl 28 | # cache=$cachedir/pmdir_relative_path 29 | # if [ -e $cache ]; then 30 | # pmdir_relative_path=$(<$cache) 31 | # else 32 | # # This trick comes from Stow's configure.ac 33 | # pmdir_relative_path=` 34 | # perl -MConfig \ 35 | # -wle '($_ = $Config{installsitelib}) 36 | # =~ s!^\Q$Config{siteprefix}/!!; \ 37 | # print'` 38 | # mkdir -p $cachedir 39 | # echo "$pmdir_relative_path" > $cache 40 | # fi 41 | # 42 | # if [ -n "$pmdir_relative_path" ]; then 43 | # add_perl5lib_path $dir/$pmdir_relative_path 44 | # fi 45 | done 46 | -------------------------------------------------------------------------------- /.shared_rc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Adam's shared interactive environment startup file 4 | # 5 | # $Id$ 6 | # 7 | # This should get run as part of setting up the interactive 8 | # environment of any sh-compatible shell; hence it should be kept as 9 | # fast and as portable as possible. Note that that means silly things 10 | # like [ ! -e foo ] rather than ! [ -e foo ] ... 11 | 12 | [ -n "$shared_rc_loaded" ] && return 0 13 | 14 | # {{{ HOME 15 | 16 | # Don't leave history files in / 17 | : ${HOME:=/} 18 | if [ "$HOME" = '/' ]; then 19 | if [ -d /root ]; then 20 | HOME=/root 21 | elif [ -d /var/tmp ]; then 22 | new_home=/var/tmp/root.tmphome 23 | if [ -d "$new_home" ] || mkdir "$new_home"; then 24 | HOME="$new_home" 25 | fi 26 | fi 27 | fi 28 | [ "$HOME" = '/' ] && echo "Warning: ~ is /" 29 | 30 | # }}} 31 | 32 | # {{{ TERM check 33 | 34 | if which tput >/dev/null 2>&1 && ! tput longname >/dev/null 2>&1; then 35 | echo >&2 "\nWarning: $TERM not present in terminfo database; falling back to xterm." 36 | TERM=xterm 37 | fi 38 | 39 | # }}} 40 | # {{{ Pager 41 | 42 | #export METAMAIL_PAGER='less -R' 43 | #export PERLDOC_PAGER='less -R' 44 | export PAGER='less' 45 | 46 | # Could also include -J for making it more obvious where matches are, 47 | # but extra first column is often annoying e.g. cut'n'paste, so better 48 | # to have it off by default. 49 | export LESS='-a -h100 -i -j15 -M -q -R -W -y100 -X' 50 | 51 | export LESSOPEN="|$ZDOTDIR/bin/lesspipe.sh %s" 52 | #export LESSCLOSE='/usr/local/bin/lessclose.sh %s %s' 53 | 54 | # Make sure synced with .cfg-post.d/shell-env 55 | export LESSKEY="$ZDOTDIR/.less" 56 | 57 | # }}} 58 | # {{{ POSIXLY_CORRECT for patch 59 | 60 | #export POSIXLY_CORRECT=yes 61 | 62 | # }}} 63 | # {{{ COLUMNS 64 | 65 | # Some programs find this handy. Unfortunately xterm gets confused 66 | # when launched with it set ... 67 | [ "${COLUMNS:-0}" -gt 0 ] && export COLUMNS 68 | 69 | # }}} 70 | # {{{ INPUTRC 71 | 72 | # no crappy RedHat inputrcs, thankyouverymuch. Which fucking *idiot* 73 | # set convert-meta to off? 74 | [ -n "$INPUTRC" ] && unset INPUTRC 75 | 76 | # }}} 77 | 78 | . $ZDOT_RUN_HOOKS .shared_rc.d 79 | 80 | shared_rc_loaded=y 81 | -------------------------------------------------------------------------------- /.shared_rc.d/md5: -------------------------------------------------------------------------------- 1 | md5 () { 2 | case "$OSTYPE" in 3 | solaris*) 4 | # DON'T DO THIS - JUST INCLUDE md5sum BUILD IN ~/local/solaris 5 | cksum "$@" 6 | ;; 7 | *) 8 | md5sum "$@" 9 | ;; 10 | esac 11 | } 12 | -------------------------------------------------------------------------------- /.shared_rc.d/nvm: -------------------------------------------------------------------------------- 1 | export NVM_DIR="$HOME/.nvm" 2 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 3 | 4 | # This will even work in zsh 5 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion 6 | -------------------------------------------------------------------------------- /.shared_rc.d/pnpm: -------------------------------------------------------------------------------- 1 | # pnpm 2 | export PNPM_HOME="/home/adam/.local/share/pnpm" 3 | case ":$PATH:" in 4 | *":$PNPM_HOME:"*) ;; 5 | *) export PATH="$PNPM_HOME:$PATH" ;; 6 | esac 7 | # pnpm end 8 | -------------------------------------------------------------------------------- /.shared_rc.d/ripgrep: -------------------------------------------------------------------------------- 1 | export RIPGREP_CONFIG_PATH=$HOME/.config/ripgreprc 2 | -------------------------------------------------------------------------------- /.shared_rc.d/sx: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Thanks to mikachu on #zsh for helping with this :-) 4 | # In zsh, setopt xtrace is immune to setopt no_localoptions, i.e. 5 | # foo () { set -x; } 6 | # is a noop, so it has to be done with aliases. 7 | 8 | #if [ "$BASHPID" = $$ ]; then 9 | if [ -n "$BASHVERSION" ] || [ -n "$ZSH_VERSION" ]; then 10 | alias sx='[[ -o xtrace ]] && set +x || set -x' 11 | else 12 | sx () { 13 | echo "Sorry, sx isn't yet implemented for this shell." >&2 14 | return 1 15 | } 16 | fi 17 | -------------------------------------------------------------------------------- /.stow-local-ignore: -------------------------------------------------------------------------------- 1 | # We don't want any old CVS repository stowing its .cvsignore 2 | # into my ~ directory; however this global stow ignore list 3 | # gets overridden by the local one in my cvs repo which does 4 | # *not* contain .cvsignore. So the .cvsignore from that 5 | # repo, and only that repo, gets stowed in ~. 6 | # 7 | # Similarly for .gitignore and my git repo. 8 | \.cvsignore 9 | \.git 10 | \.gitignore 11 | 12 | .*,v 13 | RCS 14 | CVS 15 | Attic 16 | .*~ 17 | \.\#.* 18 | \#.*\# 19 | .*\.orig 20 | .*\.old 21 | .*\.rej 22 | .*\.bak 23 | .*\.o 24 | .*\.elc 25 | .*\.pyc 26 | .*\.class 27 | .*\.flc 28 | .*\.zwc 29 | \.hg 30 | _darcs 31 | \{arch\} 32 | \.arch-ids 33 | \.arch-inventory 34 | ,,.* 35 | \.svn 36 | BitKeeper 37 | \.pcl-cvs-cache 38 | pm_to_blib 39 | blib 40 | \.nfs.+ 41 | pod2html-.+cache 42 | tags 43 | TAGS 44 | \.xvpics 45 | \.emacs\.desktop 46 | \.emacs\.backup 47 | \+\+build 48 | _build 49 | Build 50 | \.zshhistory 51 | \.bash_history 52 | .*\.rpmsave 53 | .*\.cfgsave\. 54 | config\.log 55 | autom4te\.cache 56 | .*\.log 57 | README.* 58 | LICENSE.* 59 | COPYING 60 | /doc 61 | 62 | \.autosync 63 | \.autocommit 64 | \.mypy_cache 65 | 66 | lib/perl5/Sh\.t 67 | t 68 | -------------------------------------------------------------------------------- /.url_handler.d/00-local-files: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ -e "$1" ]]; then 4 | if [[ "$1" != /* ]]; then 5 | here="$(pwd)" 6 | set "$(pwd)/$1" 7 | fi 8 | set "file://$1" 9 | fi 10 | 11 | return 1 # Carry on processing other hooks 12 | -------------------------------------------------------------------------------- /.url_handler.d/10-strip-quotes: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Work around stupid bug in exo-open (or thereabouts) which adds double-quotes 4 | # to URL 5 | 6 | if [[ "$1" =~ \"*\" ]]; then 7 | set "${1#\"}" 8 | set "${1%\"}" 9 | fi 10 | 11 | return 1 # Carry on processing other hooks 12 | -------------------------------------------------------------------------------- /.url_handler.d/10-u-template: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Telegram desktop client passes args: '%u' https://... 4 | 5 | # if [ "$1" = "'%u'" ]; then 6 | # shift 7 | # fi 8 | 9 | return 1 # Carry on processing other hooks 10 | -------------------------------------------------------------------------------- /.url_handler.d/14-notion-app-enhanced: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Not using this for now 4 | return 1 # Carry on processing other hooks 5 | 6 | notion_enhanced=~/software/web/Notion-Enhanced.AppImage 7 | 8 | if ! [ -x "$notion_enhanced" ]; then 9 | return 1 # Carry on processing other hooks 10 | fi 11 | 12 | 13 | case "$1" in 14 | https://www.notion.so/*) 15 | path="${1#https://www.notion.so/}" 16 | $notion_enhanced notion://"$path" & 17 | set -- 18 | return 0 19 | ;; 20 | esac 21 | -------------------------------------------------------------------------------- /.url_handler.d/15-switch-workspace: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if which wmctrl >&/dev/null; then 4 | wmctrl -s 1 5 | else 6 | echo "WARNING: Didn't find wmctrl on \$PATH" >&2 7 | fi 8 | 9 | return 1 # Carry on processing other hooks 10 | -------------------------------------------------------------------------------- /.url_handler.d/20-adobe-acrobat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # acrobat reader passes args: -remote openURL(url,new-window) 4 | 5 | if [ "$1" = -remote ]; then 6 | shift 7 | case "$1" in 8 | openURL*) 9 | set "${1#openURL(}" 10 | set "${1%)}" 11 | set "${1%,new-window}" 12 | ;; 13 | esac 14 | fi 15 | 16 | return 1 # Carry on processing other hooks 17 | -------------------------------------------------------------------------------- /.zsh/accounts.d/TEMPLATE: -------------------------------------------------------------------------------- 1 | # All my accounts: 2 | #my_accounts=( 3 | # {joe,root}@mymachine.com 4 | # jbloggs@myothermachine.com 5 | #) 6 | 7 | # Other people's accounts: 8 | #other_accounts=( 9 | # {fred,root}@hismachine.com 10 | # vera@hermachine.com 11 | #) 12 | -------------------------------------------------------------------------------- /.zsh/cx.d/TEMPLATE: -------------------------------------------------------------------------------- 1 | #full_stitle="${full_stitle//foo/bar}" 2 | -------------------------------------------------------------------------------- /.zsh/functions/_cf: -------------------------------------------------------------------------------- 1 | #compdef cf 2 | 3 | local expl 4 | _description expl 'font size' 5 | compadd "$expl[@]" - 1 2 3 4 6 | -------------------------------------------------------------------------------- /.zsh/functions/_cleanzip: -------------------------------------------------------------------------------- 1 | #compdef cleanzip 2 | _files -g "*.zip" -------------------------------------------------------------------------------- /.zsh/functions/_eshade: -------------------------------------------------------------------------------- 1 | #compdef eshade 2 | 3 | _message "Hex value from 00 (black) to 200 (double bright)" -------------------------------------------------------------------------------- /.zsh/functions/_hostgroup: -------------------------------------------------------------------------------- 1 | #compdef hostgroup hostgroups 2 | 3 | _hostgroup_hostgroups () { 4 | local expl 5 | _description hostgroup expl 'hostgroup' 6 | compadd "$expl[@]" - $(hostgroup -h ALL) 7 | } 8 | 9 | _hostgroup_hosts () { 10 | local expl 11 | _description host expl 'host' 12 | compadd "$expl[@]" - $(hostgroup ALL) 13 | } 14 | 15 | _hostgroup () { 16 | _arguments \ 17 | '(--hosts)-h[input contains hostnames not groups]:*:host:_hostgroup_hosts' \ 18 | '(-h)--hosts[input contains hostnames not groups]:*:host:_hostgroup_hosts' \ 19 | '(-e)--expression[input is expression not list]' \ 20 | '(--expression)-e[input is expression not list]' \ 21 | {'(--database)-f+','(-f)--database='}':alternative database file:_files' \ 22 | '(-l --lines '{'--delimiter)-d+','-d)--delimiter='}':output delimiter:' \ 23 | '(-d --delimiter '{' -l)--lines',' --lines)-l'}'[list one item per line]' \ 24 | {'(-c)--count','(--count)-c'}'[output number of items rather than actual items]' \ 25 | {'*-v','*--verbose'}'[increase verbosity (can be repeated)]' \ 26 | '(-h --hosts)*:hostgroup:_hostgroup_hostgroups' 27 | } 28 | 29 | _hostgroups () { 30 | _arguments '*:hostgroup:_hostgroup_hosts' 31 | } 32 | 33 | _$service "$@" 34 | -------------------------------------------------------------------------------- /.zsh/functions/_lh: -------------------------------------------------------------------------------- 1 | #compdef lh 2 | 3 | _users "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/_mnx: -------------------------------------------------------------------------------- 1 | #compdef mnx 2 | _files -g '*(*)' 3 | -------------------------------------------------------------------------------- /.zsh/functions/_msoffice: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | _description files expl 'MS Office files' 4 | _files "$@" "$expl[@]" -g '*.(#i)(doc|docx|xls|xlsx|ppt|pptx)' 5 | 6 | -------------------------------------------------------------------------------- /.zsh/functions/_mx: -------------------------------------------------------------------------------- 1 | #compdef mx 2 | _files -g '*(^*)' 3 | -------------------------------------------------------------------------------- /.zsh/functions/_oocalc: -------------------------------------------------------------------------------- 1 | #compdef oocalc 2 | 3 | local expl 4 | _description files expl 'OpenOffice.org Calc spreadsheets' 5 | _files "$@" "$expl[@]" -g '*.(#i)(sxc|stc)' 6 | 7 | # From /etc/mime.types: 8 | # application/vnd.sun.xml.writer sxw 9 | # application/vnd.sun.xml.writer.template stw 10 | # application/vnd.sun.xml.writer.global sxg 11 | # application/vnd.sun.xml.calc sxc 12 | # application/vnd.sun.xml.calc.template stc 13 | # application/vnd.sun.xml.impress sxi 14 | # application/vnd.sun.xml.impress.template sti 15 | # application/vnd.sun.xml.draw sxd 16 | # application/vnd.sun.xml.draw.template std 17 | # application/vnd.sun.xml.math sxm 18 | 19 | 20 | -------------------------------------------------------------------------------- /.zsh/functions/_oodraw: -------------------------------------------------------------------------------- 1 | #compdef oodraw 2 | 3 | local expl 4 | _description files expl 'OpenOffice.org Draw file' 5 | _files "$@" "$expl[@]" -g '*.(#i)(sxd|std)' 6 | 7 | # From /etc/mime.types: 8 | # application/vnd.sun.xml.writer sxw 9 | # application/vnd.sun.xml.writer.template stw 10 | # application/vnd.sun.xml.writer.global sxg 11 | # application/vnd.sun.xml.calc sxc 12 | # application/vnd.sun.xml.calc.template stc 13 | # application/vnd.sun.xml.impress sxi 14 | # application/vnd.sun.xml.impress.template sti 15 | # application/vnd.sun.xml.draw sxd 16 | # application/vnd.sun.xml.draw.template std 17 | # application/vnd.sun.xml.math sxm 18 | 19 | 20 | -------------------------------------------------------------------------------- /.zsh/functions/_ooffice: -------------------------------------------------------------------------------- 1 | #compdef oo ooffice 2 | 3 | local expl 4 | _description files expl 'OpenOffice.org files' 5 | _files "$@" "$expl[@]" -g '*.(#i)(od[mtsgpfb]|ot[tsgph]|html|sx[gwcidm]|st[wcid])' 6 | 7 | _msoffice "$@" 8 | 9 | # See also ~/.mime.types 10 | # 11 | # From OO.o 2.0 help: 12 | # 13 | # |------------------------------------+----------------| 14 | # | Document format | File extension | 15 | # |------------------------------------+----------------| 16 | # | OpenDocument Master Document | *.odm | 17 | # | OpenDocument Text | *.odt | 18 | # | OpenDocument Spreadsheet | *.ods | 19 | # | OpenDocument Drawing | *.odg | 20 | # | OpenDocument Presentation | *.odp | 21 | # | OpenDocument Formula | *.odf | 22 | # | OpenDocument Database | *.odb | 23 | # | OpenDocument Text Template | *.ott | 24 | # | OpenDocument Spreadsheet Template | *.ots | 25 | # | OpenDocument Drawing Template | *.otg | 26 | # | OpenDocument Presentation Template | *.otp | 27 | # | HTML Document Template | *.oth | 28 | # | HTML Document | *.html | 29 | # |------------------------------------+----------------| 30 | # | Before OO.o 2.0: | | 31 | # |------------------------------------+----------------| 32 | # | Master document | *.sxg | 33 | # | OpenOffice.org Writer | *.sxw | 34 | # | OpenOffice.org Calc | *.sxc | 35 | # | OpenOffice.org Impress | *.sxi | 36 | # | OpenOffice.org Draw | *.sxd | 37 | # | OpenOffice.org Math | *.sxm | 38 | # | OpenOffice.org Writer template | *.stw | 39 | # | OpenOffice.org Calc template | *.stc | 40 | # | OpenOffice.org Impress template | *.sti | 41 | # | OpenOffice.org Draw template | *.std | 42 | # |------------------------------------+----------------| 43 | -------------------------------------------------------------------------------- /.zsh/functions/_ooimpress: -------------------------------------------------------------------------------- 1 | #compdef ooimpress 2 | 3 | local expl 4 | _description files expl 'OpenOffice.org Impress presentation' 5 | _files "$@" "$expl[@]" -g '*.(#i)(sxi|sti)' 6 | 7 | # From /etc/mime.types: 8 | # application/vnd.sun.xml.writer sxw 9 | # application/vnd.sun.xml.writer.template stw 10 | # application/vnd.sun.xml.writer.global sxg 11 | # application/vnd.sun.xml.calc sxc 12 | # application/vnd.sun.xml.calc.template stc 13 | # application/vnd.sun.xml.impress sxi 14 | # application/vnd.sun.xml.impress.template sti 15 | # application/vnd.sun.xml.draw sxd 16 | # application/vnd.sun.xml.draw.template std 17 | # application/vnd.sun.xml.math sxm 18 | 19 | 20 | -------------------------------------------------------------------------------- /.zsh/functions/_oomath: -------------------------------------------------------------------------------- 1 | #compdef oomath 2 | 3 | local expl 4 | _description files expl 'OpenOffice.org Math file' 5 | _files "$@" "$expl[@]" -g '*.(#i)(sxm)' 6 | 7 | # From /etc/mime.types: 8 | # application/vnd.sun.xml.writer sxw 9 | # application/vnd.sun.xml.writer.template stw 10 | # application/vnd.sun.xml.writer.global sxg 11 | # application/vnd.sun.xml.calc sxc 12 | # application/vnd.sun.xml.calc.template stc 13 | # application/vnd.sun.xml.impress sxi 14 | # application/vnd.sun.xml.impress.template sti 15 | # application/vnd.sun.xml.draw sxd 16 | # application/vnd.sun.xml.draw.template std 17 | # application/vnd.sun.xml.math sxm 18 | 19 | 20 | -------------------------------------------------------------------------------- /.zsh/functions/_oowriter: -------------------------------------------------------------------------------- 1 | #compdef oowriter 2 | 3 | local expl 4 | _description files expl 'OpenOffice.org Writer documents' 5 | _files "$@" "$expl[@]" -g '*.(#i)(sxw|stw|sxg)' 6 | 7 | # From /etc/mime.types: 8 | # application/vnd.sun.xml.writer sxw 9 | # application/vnd.sun.xml.writer.template stw 10 | # application/vnd.sun.xml.writer.global sxg 11 | # application/vnd.sun.xml.calc sxc 12 | # application/vnd.sun.xml.calc.template stc 13 | # application/vnd.sun.xml.impress sxi 14 | # application/vnd.sun.xml.impress.template sti 15 | # application/vnd.sun.xml.draw sxd 16 | # application/vnd.sun.xml.draw.template std 17 | # application/vnd.sun.xml.math sxm 18 | 19 | 20 | -------------------------------------------------------------------------------- /.zsh/functions/_palm_PDBs: -------------------------------------------------------------------------------- 1 | #compdef pi 2 | 3 | local expl 4 | _description files expl 'Palm PDBs' 5 | _files "$@" "$expl[@]" -g '*.(#i)(prc|pdb)' 6 | -------------------------------------------------------------------------------- /.zsh/functions/_plucker-install: -------------------------------------------------------------------------------- 1 | #compdef plucker-install pli 2 | 3 | local expl 4 | _description files expl 'plucker-generated pdbs' 5 | _files "$@" "$expl[@]" -W ~/.plucker -g \*.pdb 6 | -------------------------------------------------------------------------------- /.zsh/functions/_rd: -------------------------------------------------------------------------------- 1 | #compdef rd 2 | 3 | _directories "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/_resolve_path: -------------------------------------------------------------------------------- 1 | #compdef -k complete-word ^Xf 2 | 3 | compadd -U -S '' $(abs $words[CURRENT]) 4 | -------------------------------------------------------------------------------- /.zsh/functions/_ru: -------------------------------------------------------------------------------- 1 | #compdef ru 2 | 3 | _users "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/_save_xmodmap: -------------------------------------------------------------------------------- 1 | #compdef save-xmodmap 2 | 3 | _files -W ~/.keymaps -g '*(.)' 4 | -------------------------------------------------------------------------------- /.zsh/functions/_sc: -------------------------------------------------------------------------------- 1 | #compdef sc 2 | 3 | service=systemctl 4 | _systemd "$@" 5 | -------------------------------------------------------------------------------- /.zsh/functions/_scoop: -------------------------------------------------------------------------------- 1 | #compdef scoop 2 | 3 | local expl 4 | _description files expl 'Sitescooper site file' 5 | _files "$@" "$expl[@]" \ 6 | -W ~/.sitescooper/sites 7 | # -W ~adams/palm/browsers/sitescooper-cvs/site_samples 8 | -------------------------------------------------------------------------------- /.zsh/functions/_scoop-install: -------------------------------------------------------------------------------- 1 | #compdef scoop-install 2 | 3 | local expl 4 | _description files expl 'Sitescooper-generated pdbs' 5 | _files "$@" "$expl[@]" -W ~/.sitescooper/pdb -g \*.pdb 6 | -------------------------------------------------------------------------------- /.zsh/functions/_scvs: -------------------------------------------------------------------------------- 1 | #compdef scvs 2 | 3 | local expl 4 | 5 | (( $#_CVSROOTS )) || scvs >&/dev/null 6 | 7 | _description cvs_set expl 'CVS setup' 8 | compadd "$expl[@]" - ${(k)_CVSROOTS} 9 | -------------------------------------------------------------------------------- /.zsh/functions/_service_shortcuts: -------------------------------------------------------------------------------- 1 | #compdef st ust sst usst ssp ussp sta usta sre usre srl usrl 2 | 3 | _services "$@" 4 | 5 | -------------------------------------------------------------------------------- /.zsh/functions/_spa: -------------------------------------------------------------------------------- 1 | #compdef spa 2 | 3 | _parameters "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/_str: -------------------------------------------------------------------------------- 1 | #compdef str 2 | 3 | _pids "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/_up: -------------------------------------------------------------------------------- 1 | #compdef up 2 | 3 | local expl 4 | 5 | _description files expl 'archive file' 6 | 7 | _files "$expl[@]" -g '(#i)*.(tar.(gz|Z)|tgz|tar|zip|xz|rar|xpi|jar|sar|7z|class|job|pylib|apk|egg)(-.)' 8 | -------------------------------------------------------------------------------- /.zsh/functions/_wh: -------------------------------------------------------------------------------- 1 | #compdef wh 2 | 3 | service=where 4 | _which "$@" 5 | 6 | -------------------------------------------------------------------------------- /.zsh/functions/_whenup: -------------------------------------------------------------------------------- 1 | #compdef whenup 2 | 3 | _hosts "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/_wl: -------------------------------------------------------------------------------- 1 | #compdef wl 2 | 3 | service=where 4 | _which "$@" 5 | 6 | -------------------------------------------------------------------------------- /.zsh/functions/_z: -------------------------------------------------------------------------------- 1 | #compdef z 2 | 3 | _path_files -/ -W ~ 4 | -------------------------------------------------------------------------------- /.zsh/functions/autoload_test1: -------------------------------------------------------------------------------- 1 | echo "autoload_test1 - like a shell script" 2 | -------------------------------------------------------------------------------- /.zsh/functions/autoload_test2: -------------------------------------------------------------------------------- 1 | autoload_test2 () { 2 | echo "In autoload_test2()" 3 | } 4 | 5 | echo "init" 6 | -------------------------------------------------------------------------------- /.zsh/functions/autoload_test3: -------------------------------------------------------------------------------- 1 | autoload_test3 () { 2 | echo "In autoload_test3()" 3 | } 4 | 5 | echo "init" 6 | autoload_test3 "$@" 7 | -------------------------------------------------------------------------------- /.zsh/functions/autoload_test_all: -------------------------------------------------------------------------------- 1 | autoload_tester () { 2 | fn=$1 3 | echo 4 | echo --------- $fn ---------------------------------------- 5 | echo unset KSH_AUTOLOAD 6 | unsetopt kshautoload 7 | unfunction $fn 8 | autoload $fn 9 | $fn 10 | echo "-- calling function again --" 11 | $fn 12 | 13 | echo -------------------------- 14 | 15 | echo set KSH_AUTOLOAD 16 | setopt kshautoload 17 | unfunction $fn 18 | autoload $fn 19 | $fn 20 | echo "-- calling function again --" 21 | $fn 22 | } 23 | 24 | autoload_test_all () { 25 | autoload_tester autoload_test1 26 | autoload_tester autoload_test2 27 | autoload_tester autoload_test3 28 | } 29 | 30 | # This tester itself assumes KSH_AUTOLOAD is *not* set, therefore 31 | # I need to invoke it here: 32 | autoload_test_all "$@" 33 | 34 | 35 | -------------------------------------------------------------------------------- /.zsh/functions/ba: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | source =ba 4 | -------------------------------------------------------------------------------- /.zsh/functions/bx: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | PS4="$(. ~/.bashenv.d/PS4; echo $PS4)" bash -x "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/check_hist_size: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [[ -e "$HISTFILE" ]]; then 4 | fc_out=( $(wc -l $HISTFILE) ) 5 | else 6 | fc_out=( 0 ) 7 | fi 8 | 9 | if (( fc_out[1] < 100 )); then 10 | print "\nWARNING: small $HISTFILE detected\! (${fc_out[1]:-0} lines)" 11 | fi 12 | -------------------------------------------------------------------------------- /.zsh/functions/cleanzip: -------------------------------------------------------------------------------- 1 | #autoload 2 | local force 3 | 4 | force="" 5 | if [[ "$1" = "-f" ]]; then 6 | shift 7 | force="-f" 8 | fi 9 | 10 | if [[ -z "$1" ]]; then 11 | echo "Must specify a filename" >&2 12 | exit 1 13 | fi 14 | 15 | for file in $(unzip -qql $1 | awk '{print $4}'); do 16 | [[ -e "$file" ]] || continue 17 | if [[ -f "$file" ]]; then 18 | rm $force "$file" 19 | else 20 | echo "NOT removing directory $file" 21 | fi 22 | done 23 | -------------------------------------------------------------------------------- /.zsh/functions/cvs: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | quiet='' 4 | [[ -n "$*[(r)(up|update)]" ]] && quiet='-q' 5 | 6 | home=${ZDOTDIR:-$HOME} 7 | 8 | normal_colourer=$home/bin/tty-colour-cvs 9 | diff_colourer=$home/bin/tty-colour-diff 10 | 11 | colourer='' 12 | 13 | if [[ -n "$*[(r)(up|update|co|checkout|tag|rtag)]" ]]; then 14 | colourer="$normal_colourer" 15 | elif [[ -n "$*[(r)(diff|rdiff|patch)]" ]]; then 16 | colourer="$diff_colourer" 17 | fi 18 | 19 | if [[ -n "$colourer" ]]; then 20 | command cvs $quiet "$@" | $colourer 21 | else 22 | command cvs $quiet "$@" 23 | fi 24 | -------------------------------------------------------------------------------- /.zsh/functions/cvsls: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | files=( $( cvs status -l "$@" 2>/dev/null | awk '/File: / { print $2 }' ) ) 4 | ls -d "$@" *(/) "$files[@]" 5 | -------------------------------------------------------------------------------- /.zsh/functions/cx: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # can't be bothered to support this on old zshs 4 | 5 | if [[ "$ZSH_VERSION_TYPE" == 'old' ]]; then 6 | echo "\nThis zsh doesn't support typeset -T; disabling cx." 7 | cx () { } 8 | return 1 9 | fi 10 | 11 | cx () { 12 | local short_host title_host short_from_opts suffix isuffix ssuffix 13 | 14 | # Ensure the typeset -gT doesn't result in titles=( '' ) 15 | [[ -z "$TITLES" ]] && unset TITLES 16 | 17 | # Now safe to bind TITLES to titles. 18 | (( $+titles )) || typeset -gT TITLES titles 19 | 20 | : ${TITLE_SHLVL:=$SHLVL} 21 | export TITLE_SHLVL 22 | 23 | if [[ "$SHLVL" != "$TITLE_SHLVL" ]]; then 24 | # We've changed shell; assume that the most recently pushed entry 25 | # is the starting point for the new shell. 26 | TITLE_SHLVL=$SHLVL 27 | [[ ${(t)titles} == 'array' ]] && [[ -n "$TITLES" ]] && titles=( "$TITLES" ) 28 | fi 29 | 30 | short_host=${HOST%%.*} 31 | 32 | # We use the fact that the environment variable TITLE_SHLVL can 33 | # cross process boundaries, even though the array doesn't. 34 | export TITLES 35 | 36 | if (( $# == 0 )); then 37 | # restore current setting 38 | if (( $#titles == 0 )); then 39 | new_title= 40 | else 41 | new_title="$titles[1]" 42 | fi 43 | else 44 | # push new setting 45 | 46 | # N.B. we allow pushing of "" to force default 47 | new_title="$*" 48 | 49 | if (( $#titles )); then 50 | if [[ $new_title != $titles[1] ]]; then 51 | titles=( "$new_title" "$titles[@]" ) 52 | fi 53 | else 54 | titles=( "$new_title" ) 55 | fi 56 | fi 57 | 58 | # Determine suffix. Allow force appending of auto-suffix via -l 59 | # (either from $argv or from saved title) 60 | if [[ "$new_title" == -l* || -z "$new_title" ]]; then 61 | if [[ -o kshglob ]]; then 62 | restore_kshglob='setopt kshglob' 63 | else 64 | restore_kshglob='setopt nokshglob' 65 | fi 66 | setopt kshglob 67 | new_title="${new_title##-l?( )}" 68 | eval $restore_nullglob 69 | 70 | if [[ "$USERNAME" == 'root' ]]; then 71 | suffix="${short_host}#" 72 | else 73 | suffix="$USERNAME@${short_host}" 74 | fi 75 | 76 | # w/i/s == window/icon/screen 77 | wsuffix=" : $suffix" 78 | isuffix=" : $suffix" 79 | ssuffix="|$suffix" 80 | else 81 | suffix= 82 | fi 83 | 84 | if [[ -z "$new_title" ]]; then 85 | # w/i/s == window/icon/screen 86 | full_wtitle="$suffix" 87 | full_ititle="$suffix" 88 | full_stitle="$suffix" 89 | else 90 | # w/i/s == window/icon/screen 91 | full_wtitle="$new_title$wsuffix" 92 | full_ititle="$new_title$isuffix" 93 | full_stitle="$new_title$ssuffix" 94 | fi 95 | 96 | tmp=$DEBUG_LOCAL_HOOKS 97 | DEBUG_LOCAL_HOOKS= run_hooks .zsh/cx.d 98 | DEBUG_LOCAL_HOOKS=$tmp 99 | 100 | set_title window "$full_wtitle" 101 | set_title icon "$full_ititle" 102 | [[ -n "$IN_SCREEN" || -n "$TMUX" ]] && 103 | set_title screen "$full_stitle" 104 | return 0 105 | } 106 | 107 | cx "$@" 108 | -------------------------------------------------------------------------------- /.zsh/functions/cxl: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | cxl () { 4 | # show stack 5 | echo ${(F)title} 6 | } 7 | -------------------------------------------------------------------------------- /.zsh/functions/cxp: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | cxx 4 | popd || cd 5 | -------------------------------------------------------------------------------- /.zsh/functions/cxx: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # Pop a title, and optionally push a new one. 4 | (( $#titles )) && shift titles 5 | cx "$@" 6 | -------------------------------------------------------------------------------- /.zsh/functions/enable_nullglob: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # Portable way of temporarily enabling null globbing: 4 | # 5 | # . path/to/this/script 6 | # # do glob 7 | # restore_nullglob 8 | # 9 | # Needed for handling word-separated pseudo-arrays portably. 10 | # See also enable_nullglob. 11 | 12 | enable_nullglob () { 13 | # Ugh! 14 | restore_nullglob= 15 | if [ -n "$ZSH_VERSION" ]; then 16 | if [[ -o nullglob ]]; then 17 | restore_nullglob='setopt nullglob' 18 | else 19 | restore_nullglob='setopt nonullglob' 20 | fi 21 | setopt nullglob 22 | elif [ -n "$BASH_VERSION" ]; then 23 | case "$BASH_VERSION" in 24 | 1*) 25 | restore_nullglob="allow_null_glob_expansion=$allow_null_glob_expansion" 26 | allow_null_glob_expansion=0 27 | ;; 28 | [2-5].*) 29 | restore_nullglob=`shopt -p nullglob` 30 | shopt -s nullglob 31 | ;; 32 | *) 33 | echo "Unknown \$BASH_VERSION $BASH_VERSION ! Don't know how to enable_nullglob" >&2 34 | return 1 35 | ;; 36 | esac 37 | else 38 | echo "Don't know how to enable null globbing in this shell (SHELL=$SHELL)" >&2 39 | return 1 40 | fi 41 | } 42 | 43 | restore_nullglob () { 44 | eval "$restore_nullglob" 45 | } 46 | 47 | enable_nullglob "$@" 48 | -------------------------------------------------------------------------------- /.zsh/functions/enable_wordsplit: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # Portable way of temporarily enabling word splitting: 4 | # 5 | # . path/to/this/script 6 | # # do glob 7 | # restore_wordsplit 8 | # 9 | # Needed for handling word-separated pseudo-arrays portably. 10 | # See also enable_nullglob. 11 | 12 | enable_wordsplit () { 13 | restore_wordsplit= 14 | if [ -n "$ZSH_VERSION" ]; then 15 | if [[ -o sh_word_split ]]; then 16 | restore_wordsplit='setopt sh_word_split' 17 | else 18 | restore_wordsplit='setopt no_sh_word_split' 19 | fi 20 | setopt sh_word_split 21 | elif [ -n "$BASH_VERSION" ]; then 22 | : # nothing to do? 23 | else 24 | # Probably safe to assume word splitting will happen - should do in Bourne at least, 25 | # and probably Korn. 26 | return 0 27 | # echo "Don't know how to enable word splitting in this shell (SHELL=$SHELL)" >&2 28 | # return 1 29 | fi 30 | } 31 | 32 | restore_wordsplit () { 33 | eval "$restore_wordsplit" 34 | } 35 | 36 | enable_wordsplit "$@" 37 | -------------------------------------------------------------------------------- /.zsh/functions/etint: -------------------------------------------------------------------------------- 1 | # Set Eterm tint 2 | 3 | etint () { 4 | case "$*" in 5 | 6 | # old Eterm codes: 7 | # red) echo -e "\e]6;2;0xff8080\a" ;; 8 | # green) echo -e "\e]6;2;0x80ff80\a" ;; 9 | # blue) echo -e "\e]6;2;0x8080ff\a" ;; 10 | # cyan) echo -e "\e]6;2;0x80ffff\a" ;; 11 | # magenta) echo -e "\e]6;2;0xff80ff\a" ;; 12 | # yellow) echo -e "\e]6;2;0xffff80\a" ;; 13 | # *) echo -e "\e]6;2;0xffffff\a" ;; 14 | 15 | # new eterm codes: 16 | red) cmod=( a0 50 50 ) ;; 17 | green) cmod=( 50 a0 50 ) ;; 18 | blue) cmod=( 50 50 a0 ) ;; 19 | cyan) cmod=( 50 a0 a0 ) ;; 20 | magenta) cmod=( a0 50 a0 ) ;; 21 | yellow) cmod=( a0 a0 50 ) ;; 22 | *) cmod=( a0 a0 a0 ) ;; 23 | esac 24 | 25 | i=1 26 | echo -ne "\e]" 27 | for rgb in red green blue; do 28 | brightness=$cmod[$i] 29 | echo -ne "6;1;bg;$rgb;brightness;0x$brightness" 30 | (( i < 3 )) && echo -n ';' 31 | (( i++ )) 32 | done 33 | echo -ne "\a" 34 | } 35 | 36 | _etint () { 37 | local expl 38 | _description tint expl 'tint colour' 39 | compadd "$expl[@]" - red green blue cyan magenta yellow 40 | } 41 | compdef _etint etint 42 | 43 | etint "$@" 44 | -------------------------------------------------------------------------------- /.zsh/functions/extglob: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # Temporary extended globbing 4 | # 5 | # I have extended_glob set all the time anyway, but this is nice 6 | # for those who don't. Thanks to Bart Schaefer for this one. 7 | 8 | function ext_glob { 9 | setopt localoptions extendedglob 10 | local command="$1" 11 | shift 12 | $==command $==~* # redo globbing on arguments 13 | } 14 | 15 | function extglob () { 16 | noglob ext_glob "$@" 17 | } 18 | 19 | extglob "$@" 20 | -------------------------------------------------------------------------------- /.zsh/functions/fext: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | suffix="$1" 4 | 5 | if [[ "$suffix" == [a-zA-Z]* ]]; then 6 | suffix=".$suffix" 7 | fi 8 | 9 | shift 10 | find "$@" -name "*$suffix" 11 | -------------------------------------------------------------------------------- /.zsh/functions/find_hooks: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [ $# != 1 ]; then 4 | echo "Usage: find_hooks " >&2 5 | return 1 6 | fi 7 | 8 | . $ZDOTDIR/.zsh/functions/run_hooks DEFUN # this will only load the functions we need 9 | 10 | iterate_hooks find "$@" 11 | 12 | . $ZDOTDIR/.zsh/functions/enable_wordsplit 13 | 14 | if [ -n "$hooks_found" ]; then 15 | if [ -n "$ZSH_VERSION" ]; then 16 | setopt local_options no_extended_glob 17 | fi 18 | for hook in $hooks_found; do 19 | echo "$hook" 20 | done 21 | fi 22 | 23 | restore_wordsplit 24 | -------------------------------------------------------------------------------- /.zsh/functions/fmbox: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | locate "$HOME/mail/*${^@}" 4 | -------------------------------------------------------------------------------- /.zsh/functions/ftp: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if which lftp >&/dev/null; then 4 | lftp "$@" 5 | elif which ncftp >&/dev/null; then 6 | ncftp "$@" 7 | fi 8 | -------------------------------------------------------------------------------- /.zsh/functions/histmerge: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | echo "Before:" 4 | history -5 5 | 6 | fc -RI 7 | fc -W 8 | 9 | echo 10 | echo "After (broken?):" 11 | history -5 12 | -------------------------------------------------------------------------------- /.zsh/functions/imv: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | me="$(print -P %N)" 4 | 5 | if [[ "$1" == "--help" ]]; then 6 | print 'Usage: $me [OPTION]... SOURCE 7 | Renames SOURCE, allowing interactive editing of the new name. 8 | 9 | The following options are passed on to mv(1): 10 | -b, -u' >&2 11 | return 0 12 | fi 13 | 14 | opts=() 15 | while getopts :bu opt; do 16 | if [[ $opt = "?" ]]; then 17 | print "$me: unrecognized option: -$OPTARG" >&2 18 | print "Try \`$me --help' for more information." >&2 19 | return 1 20 | fi 21 | opts=( "$opts[@]" "-$opt" ) 22 | done 23 | (( OPTIND > 1 )) && shift $(( OPTIND - 1 )) 24 | 25 | if (( $# == 0 )); then 26 | print "$me: missing file argument" 27 | return 1 28 | fi 29 | 30 | if (( $# > 1 )); then 31 | print "$me: too many arguments" 32 | return 1 33 | fi 34 | 35 | src="$1" 36 | 37 | if ! [[ -e "$src" ]]; then 38 | print "$me: can't stat source $src" 39 | return 1 40 | fi 41 | 42 | dest="$src" 43 | vared -p 'New name: ' dest 44 | 45 | if [[ "$src" == "$dest" ]]; then 46 | print "$me: no change in name" 47 | return 1 48 | fi 49 | 50 | if [[ -e "$dest" ]]; then 51 | echo -n "$me: $dest already exists; replace? " 52 | if ! read -q replace; then 53 | echo "Aborted." 54 | return 1 55 | fi 56 | fi 57 | 58 | mv "$opts[@]" -- "$src" "$dest" 59 | 60 | 61 | -------------------------------------------------------------------------------- /.zsh/functions/kill-region-or-backward-big-word: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [[ "$MARK" -eq 0 || "$MARK" -eq "$CURSOR" ]]; then 4 | local WORDCHARS="${_my_extended_wordchars_slash}" 5 | zle .backward-kill-word 6 | else 7 | zle .kill-region 8 | fi 9 | -------------------------------------------------------------------------------- /.zsh/functions/kill-region-or-backward-word: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [[ "$MARK" -eq 0 || "$MARK" -eq "$CURSOR" ]]; then 4 | zle .backward-kill-word 5 | else 6 | zle .kill-region 7 | fi 8 | -------------------------------------------------------------------------------- /.zsh/functions/magic-backward-word: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # See also magic-forward-word etc. 4 | 5 | if [[ "$#BUFFER" == 0 ]]; then 6 | zle up-line-or-history 7 | fi 8 | 9 | zle emacs-backward-word 10 | -------------------------------------------------------------------------------- /.zsh/functions/magic-forward-char: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # For easily altering the first word of the previous line; 4 | # I do this quite a lot, e.g. 5 | # ls foo 6 | # then 7 | # l foo 8 | # 9 | # See also magic-forward-word 10 | 11 | if [[ "$#BUFFER" == 0 ]]; then 12 | zle up-line-or-history 13 | CURSOR=0 14 | zle forward-char 15 | else 16 | zle forward-char 17 | fi 18 | -------------------------------------------------------------------------------- /.zsh/functions/magic-forward-to-space: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # For easily altering the first word of the previous line; 4 | # I do this quite a lot, e.g. 5 | # ls foo 6 | # then 7 | # l foo 8 | # 9 | # See also magic-forward-char 10 | 11 | if [[ "$#BUFFER" == 0 ]]; then 12 | zle up-line-or-history 13 | zle beginning-of-line 14 | fi 15 | 16 | zle forward-to-space 17 | -------------------------------------------------------------------------------- /.zsh/functions/magic-forward-word: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # For easily altering the first word of the previous line; 4 | # I do this quite a lot, e.g. 5 | # ls foo 6 | # then 7 | # l foo 8 | # 9 | # See also magic-forward-char 10 | 11 | if [[ "$#BUFFER" == 0 ]]; then 12 | zle up-line-or-history 13 | CURSOR=0 14 | zle emacs-forward-word 15 | else 16 | zle forward-word 17 | fi 18 | -------------------------------------------------------------------------------- /.zsh/functions/magic-kill-word: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # See also magic-forward-word etc. 4 | 5 | if [[ "$#BUFFER" == 0 ]]; then 6 | zle up-line-or-history 7 | zle beginning-of-line 8 | fi 9 | 10 | zle .kill-word 11 | -------------------------------------------------------------------------------- /.zsh/functions/magic-space: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # Useful for inserting a new word where the cursor is 4 | 5 | # See also magic-forward-word etc. 6 | 7 | if [[ $LBUFFER[-1] != ' ' ]]; then 8 | zle self-insert ' ' 9 | fi 10 | 11 | if [[ $RBUFFER[1] != ' ' ]]; then 12 | zle self-insert ' ' 13 | zle .backward-char 14 | fi 15 | -------------------------------------------------------------------------------- /.zsh/functions/mcd: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | mkdir -p "$@" 4 | cd "$@" 5 | -------------------------------------------------------------------------------- /.zsh/functions/ncftp: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | setopt local_traps 4 | trap 'cxx' INT EXIT QUIT KILL 5 | cx ncftp 6 | command ncftp "$@" 7 | 8 | 9 | -------------------------------------------------------------------------------- /.zsh/functions/nullglob: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | THIS DOESN'T WORK - keeping for reference. 4 | 5 | See disable_nullglob 6 | 7 | # Nasty, more portable way of doing bash's shopt -s nullglob :-( 8 | glob="$dir/$hook.d/*" 9 | glob_cmd="echo $glob" 10 | 11 | result=`echo $glob 2>/dev/null` 12 | [ "$result" = "$glob_cmd" ] && result= 13 | -------------------------------------------------------------------------------- /.zsh/functions/only: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [[ "$1" == diffs ]]; then 4 | awk '/^diff/ {print $9}' 5 | else 6 | awk '/^Only in '"$1"'/ {s=$3 $4; sub(": *", "/", s); print s}' 7 | fi 8 | -------------------------------------------------------------------------------- /.zsh/functions/oo: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | libreoffice "$@" &! 4 | 5 | -------------------------------------------------------------------------------- /.zsh/functions/pdf: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | command pdf "$@" &! 4 | 5 | -------------------------------------------------------------------------------- /.zsh/functions/pmg: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | pmgrep "$@" 4 | -------------------------------------------------------------------------------- /.zsh/functions/pmgrep: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | grep_args=() 4 | 5 | while [[ "$1" == -* ]]; do 6 | grep_args=( "$grep_args[@]" "$1" ) 7 | shift 8 | [[ "$grep_args[-1]" == '--' ]] && break 9 | done 10 | 11 | grep_args=( "$grep_args[@]" "$1" ) 12 | shift 13 | 14 | find "$@" -name '*.p[ml]' | xargs egrep "$grep_args[@]" 15 | -------------------------------------------------------------------------------- /.zsh/functions/prompt_adam2: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | 4 | if [[ -d /proc && -r /proc/$PPID/cmdline ]] && 5 | egrep -q 'watchlogs|kates|nexus|vga' /proc/$PPID/cmdline; 6 | then 7 | # probably OK for fancy graphic prompt 8 | if prompt -h adam2 | grep -q 8bit; then 9 | prompt adam2 8bit $adam2_colors 10 | else 11 | prompt adam2 $adam2_colors 12 | fi 13 | else 14 | if prompt -h adam2 | grep -q plain; then 15 | prompt adam2 plain $adam2_colors 16 | else 17 | prompt adam2 $adam2_colors 18 | fi 19 | fi 20 | -------------------------------------------------------------------------------- /.zsh/functions/sc: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if (( EUID == 0 )); then 4 | systemctl "$@" 5 | else 6 | sudo systemctl "$@" 7 | fi 8 | -------------------------------------------------------------------------------- /.zsh/functions/scvs: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [[ $ZSH_VERSION_TYPE != 'new' ]]; then 4 | echo Need new zsh for scvs 5 | exit 1 6 | fi 7 | 8 | scvs () { 9 | if [[ -z "$1" ]]; then 10 | cat < [ options ] 12 | CVSROOT=${CVSROOT-undefined} 13 | CVS_RSH=${CVS_RSH-undefined} 14 | export CVSROOT CVS_RSH 15 | EOF 16 | return 17 | fi 18 | 19 | tag="$1" 20 | 21 | shift 22 | 23 | if (( ${+_CVSROOTS[$tag]} )); then 24 | echo "CVSROOT=$_CVSROOTS[$tag]" 25 | export CVSROOT="$_CVSROOTS[$tag]" 26 | else 27 | echo "Warning: CVSROOT for $tag undefined; not setting." >&2 28 | fi 29 | 30 | if (( ${+_CVS_RSHS[$tag]} )); then 31 | echo "CVS_RSH=$_CVS_RSHS[$tag]" 32 | export CVS_RSH="$_CVS_RSHS[$tag]" 33 | else 34 | echo "Warning: CVS_RSH for $tag undefined; not setting." >&2 35 | fi 36 | } 37 | 38 | typeset -Ag _CVSROOTS _CVS_RSHS 39 | _CVSROOTS=( 40 | # Put your own CVSROOTs here 41 | # local /usr/local/cvsroot 42 | local $HOME/.CVSROOT 43 | mutt :pserver:anonymous@ftp.guug.de:/home/roessler/cvs 44 | ### BEGIN PRIVATE 45 | adamspiers adam@adamspiers.org:/home/adam/.CVSROOT 46 | banjo adam@banjo.celticmusic.com:/home/adam/.CVSROOT 47 | f5 adam@f5.mandolinarchive.com:/home/adam/.CVSROOT 48 | sourceforge_anon :pserver:anonymous@cvs.sourceforge.net:/cvsroot/\$1 49 | sourceforge :ext:adamspiers@cvs.sourceforge.net:/cvsroot/\$\{1:l\} 50 | 51 | zsh_sf_local_write adamspiers@cvs1:/cvsroot/zsh 52 | zsh_sf_local :pserver:anonymous@cvs1:/cvsroot/zsh 53 | zsh_remote_write adamspiers@cvs.zsh.sourceforge.net:/cvsroot/zsh 54 | zsh_remote :pserver:anonymous@cvs.zsh.sourceforge.net:/cvsroot/zsh 55 | ### END PRIVATE 56 | ) 57 | 58 | _CVS_RSHS=( 59 | # Put your own CVS_RSHs here, e.g. 60 | # foo.bar.com ssh 61 | # foo.baz.com rsh 62 | local '' 63 | ### BEGIN PRIVATE 64 | # lb-plig ~/bin/cvs-ssh 65 | adamspiers ssh 66 | banjo ssh 67 | f5 ssh 68 | sourceforge ssh 69 | zsh_local_write ssh 70 | zsh_local ssh 71 | zsh_remote_write ssh 72 | zsh_remote ssh 73 | ### END PRIVATE 74 | ) 75 | 76 | scvs "$@" 77 | -------------------------------------------------------------------------------- /.zsh/functions/set_title: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | local num title 4 | 5 | # Don't output anything if STDOUT isn't a tty 6 | [[ -t 1 ]] || return 1 7 | 8 | type="$1" 9 | 10 | if (( $# > 0 )); then 11 | shift 12 | title="$1" 13 | fi 14 | 15 | window_or_icon () { 16 | code="$1" 17 | # Other checks will need to be added here. Could switch on output of tty(1). 18 | if [[ "$TERM" == 'linux' ]]; then 19 | : 20 | #echo "Cannot currently display '$1' title; only remembering value set." 21 | else 22 | # note screen will swallow this 23 | echo -n "\e]$code;$title\a" 24 | fi 25 | } 26 | 27 | case "$type" in 28 | icon) window_or_icon 1;; 29 | window) window_or_icon 2;; 30 | screen) echo -n "\ek$title\e\\" ;; 31 | *) print "Usage: set_title ( window | icon | screen ) " 32 | return 1 ;; 33 | esac 34 | 35 | 36 | -------------------------------------------------------------------------------- /.zsh/functions/spa: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | echo "${(FP)${1:-path}}" 4 | -------------------------------------------------------------------------------- /.zsh/functions/srm: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | # Safe ReMove 4 | 5 | if [[ -z "$TRASHCAN" ]]; then 6 | echo "TRASHCAN not defined in environment, aborting." >&2 7 | return 1 8 | fi 9 | 10 | if [[ $# -eq 0 ]]; then 11 | cat <<EOF >&2 12 | Usage: $0 <files to trash> 13 | TRASHCAN is currently $TRASHCAN 14 | EOF 15 | return 1 16 | fi 17 | 18 | if cp -a --parents --target-directory="$TRASHCAN" "$@"; then 19 | rm -rf "$@" 20 | else 21 | echo "Safe remove to $TRASHCAN failed." >&2 22 | return 1 23 | fi 24 | 25 | -------------------------------------------------------------------------------- /.zsh/functions/ster: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | stty erase '^?' 4 | -------------------------------------------------------------------------------- /.zsh/functions/str: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | case "$1" in 4 | [0-9]*) 5 | pid="$1" 6 | ;; 7 | *) 8 | pids=( `pgrep "$1"` ) 9 | if (( $#pids == 0 )); then 10 | echo "Didn't find any pids for $1, trying again with args..." >&2 11 | pids=( `pgrep -f "$1"` ) 12 | if (( $#pids == 0 )); then 13 | echo "Still didn't find any pids; giving up." >&2 14 | return 1 15 | fi 16 | fi 17 | 18 | if (( $#pids > 1 )); then 19 | echo "Found $#pids pids for $1: $pids" >&2 20 | ps -fp `pgrep -d, "$1"` 21 | return 1 22 | fi 23 | 24 | pid="$pids[1]" 25 | ;; 26 | esac 27 | 28 | strace -f -p "$pid" 29 | -------------------------------------------------------------------------------- /.zsh/functions/switch_cvsroot: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | dirs=( `list-checked-out-dirs -t` ) 4 | echo "Will switch following dirs to \$CVSROOT ($CVSROOT):" 5 | echo " $dirs" 6 | read -q yesno"?Continue? " || return 7 | 8 | for d in "$dirs[@]"; do 9 | z $d 10 | cvsroot -r $CVSROOT 11 | echo Switched $d 12 | done 13 | 14 | z 15 | cvsroot $CVSROOT 16 | echo "Switched ~" 17 | -------------------------------------------------------------------------------- /.zsh/functions/th: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | source =th 4 | -------------------------------------------------------------------------------- /.zsh/functions/transpose-big-words: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | local WORDCHARS="${_my_extended_wordchars_slash}" 4 | 5 | # first make sure we're aligned with the start of the 2nd word, 6 | # removing all spaces in between the two words so that there's 7 | # no trailing spaces at the end after the transpose is complete. 8 | while [[ "$RBUFFER[0]" == ' ' ]]; do 9 | zle .delete-char 10 | done 11 | while [[ "$LBUFFER[-1]" == ' ' ]]; do 12 | zle .backward-delete-char 13 | done 14 | 15 | # transpose 16 | zle kill-big-word 17 | zle backward-to-space 18 | zle .yank 19 | 20 | # add a space back in between 21 | LBUFFER="${LBUFFER} " 22 | -------------------------------------------------------------------------------- /.zsh/functions/v1: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | export TERM=vt100 4 | -------------------------------------------------------------------------------- /.zsh/functions/v2: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | export TERM=vt220 4 | -------------------------------------------------------------------------------- /.zsh/functions/ve: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | export TERM=Eterm-color 4 | -------------------------------------------------------------------------------- /.zsh/functions/vterm_printf: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | if [ -n "$TMUX" ]; then 4 | # Tell tmux to pass the escape sequences through 5 | # (Source: http://permalink.gmane.org/gmane.comp.terminal-emulators.tmux.user/1324) 6 | printf "\ePtmux;\e\e]%s\007\e\\" "$1" 7 | elif [ "${TERM%%-*}" = "screen" ]; then 8 | # GNU screen (screen, screen-256color, screen-256color-bce) 9 | printf "\eP\e]%s\007\e\\" "$1" 10 | else 11 | printf "\e]%s\e\\" "$1" 12 | fi 13 | -------------------------------------------------------------------------------- /.zsh/functions/vx: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | export TERM=xterm-color 4 | -------------------------------------------------------------------------------- /.zsh/functions/wh: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | for thing in "$@"; do 4 | if [[ `where "$thing"` == *'builtin autoload'* ]]; then 5 | autoload +X "$thing" 6 | echo "# Note: $thing was autoloaded" 7 | fi 8 | done 9 | 10 | where "$@" 11 | 12 | 13 | -------------------------------------------------------------------------------- /.zsh/functions/xt: -------------------------------------------------------------------------------- 1 | #autoload 2 | # eXTract 3 | 4 | # Use this to untar after doing a tar ztvf/tvf/ztf or unzip -l command 5 | 6 | # Thanks to Bart Schaefer for this one 7 | fc -e - tvf=xf ztf=zxf jtf=jxf '-l '= -1 8 | 9 | -------------------------------------------------------------------------------- /.zsh/functions/zrec: -------------------------------------------------------------------------------- 1 | #autoload 2 | 3 | _my_zrecompile () { 4 | _func_dir="${fpath[(r)*share/zsh*/functions*]/functions\/*/functions}" 5 | echo "Found site-wide functions at $_func_dir" 6 | 7 | _compinit_dir=( $_func_dir/**/compinit ) 8 | _compinit_dir=${${_compinit_dir[1]}%/compinit} 9 | _Completions_glob=( $_func_dir/Completion/**/_*(.N) ) 10 | _Prompts_glob=( $_func_dir/Prompts/prompt*(.) ) 11 | _site_funcs=( 12 | "$_Completions_glob[@]" 13 | "$_Prompts_glob[@]" 14 | /etc/zsh_completion.d/**(.N) 15 | ) 16 | 17 | # zrecompile cheatsheet: 18 | # 19 | # -p means sets of arguments in between -- get passed to 20 | # zcompile. See comments at top of the zrecompile source file 21 | # in /usr/share/zsh/functions/Misc/zrecompile for examples. 22 | # -R copies .zwc into shell process memory 23 | # -M mmaps the .zwc 24 | # -U suppresses alias expansion during reading of function 25 | # -z autoloads function as if KSH_AUTOLOAD unset. 26 | # -k autoloads function as if KSH_AUTOLOAD set. 27 | # Without -k or -z, takes value of KSH_AUTOLOAD when compiled 28 | # file is read. 29 | 30 | # Use -R for scripts, -M for autoloads 31 | # Info says -U and -z to be used for system functions. 32 | if [[ -w $_compinit_dir ]]; then 33 | _compinits=( 34 | -R $_compinit_dir/compinit -- 35 | -R $_compinit_dir/compaudit -- 36 | -R $_compinit_dir/compdump -- 37 | ) 38 | else 39 | _compinits=() 40 | fi 41 | 42 | # deal with shared $HOME 43 | zwcdir=~/.zsh/$ZSH_VERSION 44 | [ -d "$zwcdir" ] || mkdir -p "$zwcdir" 45 | rm -f ~/.zsh/*.zwc(N) # clean up old versions 46 | 47 | zrecompile "$@" -p -- \ 48 | -R ~/.zshenv -- \ 49 | -R ~/.zshrc -- \ 50 | "$_compinits[@]" \ 51 | -M -U $zwcdir/my-functions.zwc ~/.zsh/functions/*(-*) -- \ 52 | -M -U $zwcdir/site-functions.zwc "$_site_funcs[@]" -- \ 53 | -R ~/.zcompdump 54 | } 55 | 56 | zrec () { 57 | if [ -n "$OTHER_USER" ]; then 58 | echo "zrec invoked when OTHER_USER; skipping" >&2 59 | return 1 60 | fi 61 | 62 | rm -f ~/.zsh/functions.zwc # in case old versions are still around 63 | 64 | # Some really weird shit happens when you remove an entry from the 65 | # _comps array - it persists unless you really try to get rid of 66 | # it. Haven't figured out exactly how it refuses to die yet. 67 | rm -f ~/.zcompdump* 68 | compinit 69 | 70 | _my_zrecompile 71 | 72 | # This should be safe now. 73 | if [[ "$-" == *i* ]]; then 74 | restart 75 | fi 76 | } 77 | 78 | zrec "$@" 79 | -------------------------------------------------------------------------------- /.zsh/users.d/TEMPLATE: -------------------------------------------------------------------------------- 1 | # users=( tom dick harry "$users[@]" ) 2 | -------------------------------------------------------------------------------- /.zshenv: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | # 3 | # .zshenv 4 | # for zsh 3.1.6 and newer (may work OK with earlier versions) 5 | # 6 | # by Adam Spiers <adam@spiers.net> 7 | # 8 | # Best viewed in emacs folding mode (folding.el). 9 | # (That's what all the # {{{ and # }}} are for.) 10 | # 11 | # This gets run even for non-interactive shells; 12 | # keep it as fast as possible. 13 | # 14 | # N.B. This is for zsh-specific environment stuff. Put generic, 15 | # portable environment settings in .shared_env instead, so that they 16 | # take effect for bash and ksh. 17 | 18 | # Allow disabling of entire environment suite 19 | [ -n "$INHERIT_ENV" ] && return 0 20 | 21 | # Stop bad system-wide scripts interfering. 22 | setopt NO_global_rcs 23 | 24 | # {{{ What version are we running? 25 | 26 | shell=zsh 27 | 28 | ZSH_VERSION_TYPE=new 29 | 30 | # }}} 31 | 32 | # {{{ zdotdir 33 | 34 | # ZDOTDIR is a zsh-ism but it's a good concept so we generalize it to 35 | # the other shells. 36 | 37 | # This allows us to have a good set of .*rc files etc. in one place 38 | # and to be able to reuse that from a different account (e.g. root). 39 | 40 | # We have to do some of this both here and in .shared_env to avoid 41 | # a chicken and egg thing when looking for the right .shared_env. 42 | 43 | zdotdir=${ZDOTDIR:-$HOME} 44 | export ZDOTDIR="$zdotdir" 45 | 46 | # }}} 47 | 48 | [[ -e $zdotdir/.shared_env ]] && . $zdotdir/.shared_env 49 | 50 | sh_load_status ".zshenv already started before .shared_env" 51 | 52 | setopt extended_glob 53 | 54 | sh_load_status "search paths" 55 | 56 | # {{{ prevent duplicates in path variables 57 | 58 | # path and manpath are special - "hardcoded" tie with $(MAN)PATH 59 | typeset -U path 60 | typeset -U manpath 61 | export MANPATH 62 | 63 | typeset -TU LD_LIBRARY_PATH ld_library_path 64 | typeset -TU PERL5LIB perl5lib 65 | 66 | # }}} 67 | # {{{ Ruby libraries 68 | 69 | typeset -TU RUBYLIB rubylib 70 | export RUBYLIB 71 | rubylib=( 72 | ~/lib/[r]uby{/site_ruby,}{/1.*,}{/i?86*,}(N) 73 | ~/lib/[r]uby(N) 74 | $rubylib 75 | ) 76 | 77 | # }}} 78 | # {{{ Python libraries 79 | 80 | typeset -TU PYTHONPATH pythonpath 81 | export PYTHONPATH 82 | 83 | # }}} 84 | 85 | # {{{ fpath/autoloads 86 | 87 | sh_load_status "fpath/autoloads" 88 | 89 | typeset -U fpath 90 | fpath=( 91 | {~,$zdotdir}/.[z]sh/$ZSH_VERSION/*.zwc(N) 92 | {~,$zdotdir}/{.[z]sh,[l]ib/zsh}/{functions{,/person-$ZDOTUSER,/host-${HOST%%.*}},scripts}(N) 93 | /etc/zsh_completion.d 94 | $fpath 95 | ) 96 | 97 | # Autoload shell functions from all directories in $fpath. Restrict 98 | # functions from $zdotdir/.zsh to ones that have the executable bit 99 | # on. (The executable bit is not necessary, but gives you an easy way 100 | # to stop the autoloading of a particular shell function). 101 | # 102 | # The ':t' is a history modifier to produce the tail of the file only, 103 | # i.e. dropping the directory path. The 'x' glob qualifier means 104 | # executable by the owner (which might not be the same as the current 105 | # user). 106 | 107 | for dirname in $fpath; do 108 | case "$dirname" in 109 | $zdotdir/.zsh*) fns=( $dirname/*~*~(-N.x:t) ) ;; 110 | *) fns=( $dirname/*~*~(-N.:t) ) ;; 111 | esac 112 | (( $#fns )) && autoload "$fns[@]" 113 | done 114 | 115 | # }}} 116 | 117 | # {{{ Specific to hosts 118 | 119 | run_hooks .zshenv.d 120 | 121 | # }}} 122 | -------------------------------------------------------------------------------- /.zshrc.other-user: -------------------------------------------------------------------------------- 1 | # If I (Adam) want to have all my nice shell stuff from another 2 | # uid (e.g. root), just log in as that user and do 3 | # 4 | # ln -s ~adam/.zshrc.other-user ~/.zshrc 5 | # 6 | # (or copy and edit if the code below can't find ZDOTDIR) 7 | # 8 | # If someone else wants all my nice stuff from their uid on the 9 | # same machine, copy this file to ~/.zshrc of that uid and 10 | # delete the ZDOTUSER setting. 11 | 12 | if [ -e /home/adam ]; then 13 | export ZDOTDIR=/home/adam 14 | elif [ -e /home/aspiers ]; then 15 | export ZDOTDIR=/home/aspiers 16 | else 17 | echo "Cannot find ZDOTDIR! Edit ~/.zshrc" 18 | return 1 19 | fi 20 | 21 | export ZDOTUSER=adam.spiers 22 | 23 | [ -n "$ZDOTDIR" ] && . $ZDOTDIR/.ns 24 | -------------------------------------------------------------------------------- /bin/AC-online: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Assume on-line if unknown 4 | AC-state | egrep -q 'on-line|unknown' 5 | -------------------------------------------------------------------------------- /bin/AC-state: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | state_file=/proc/acpi/ac_adapter/AC/state 4 | if [ -e "$state_file" ]; then 5 | cat "$state_file" 6 | else 7 | echo unknown 8 | fi -------------------------------------------------------------------------------- /bin/abs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # abs -- convert to absolute path(s), all symlinks resolved 4 | # Copyright (c) 2001 Adam Spiers <adam@spiers.net> 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 | 19 | use strict; 20 | use warnings; 21 | 22 | use Cwd; 23 | use File::Spec; 24 | use FindBin qw($RealScript); 25 | use Getopt::Long; 26 | 27 | use Sh qw(abs_path_by_chasing abs_path_by_chdir); 28 | 29 | my %opts = (); 30 | GetOptions(\%opts, 'help|h'); 31 | 32 | if ($opts{help} || @ARGV == 0) { 33 | die <<USAGE; 34 | Usage: $RealScript <path> [ <path> ... ] 35 | USAGE 36 | } 37 | 38 | foreach my $path (@ARGV) { 39 | $path = "./$path" if $path !~ m!/!; 40 | print abs_path_by_chasing($path), "\n"; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /bin/active-since: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me=`basename $0` 4 | 5 | usage () { 6 | if [ -n "$1" ]; then 7 | echo "$*" >&2 8 | echo 9 | fi 10 | 11 | cat <<EOF >&2 12 | Usage: $me THRESHOLD 13 | EOF 14 | exit 1 15 | } 16 | 17 | if [ "$1" == '-h' ] || [ "$1" == '--help' ]; then 18 | usage 19 | fi 20 | 21 | if [ -z "$1" ]; then 22 | usage 23 | fi 24 | 25 | threshold_epoch=`date +%s -d "$*"` 26 | threshold_human=`date -d "$*"` 27 | # don't use uidle -x since we don't want mouse movement 28 | # to trigger a reboot! 29 | if ! last_active_epoch=`uidle -lx`; then 30 | uidle -lx -v5 > ~/.log/uidle-lx.broke 2>&1 31 | echo "uidle -l failed; aborting." >&2 32 | exit 1 33 | fi 34 | if ! last_active_human=`uidle -lhx`; then 35 | uidle -lhx -v5 > ~/.log/uidle-lhx.broke 2>&1 36 | echo "uidle -lh failed; aborting." >&2 37 | exit 1 38 | fi 39 | 40 | if [ "$last_active_epoch" -gt "$threshold_epoch" ]; then 41 | echo "$last_active_human; after $threshold_human" 42 | exit 0 43 | else 44 | echo "$last_active_human; before $threshold_human" 45 | exit 1 46 | fi 47 | -------------------------------------------------------------------------------- /bin/age-of: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Show the age in seconds of a running or completed command which 4 | # was run under the age-track wrapper. exit 0 if still running, 1 otherwise. 5 | 6 | AGE_DIR="$HOME/.run/age" 7 | 8 | me=`basename $0` 9 | 10 | usage () { 11 | cat <<EOF >&2 12 | Usage: $me [-n] COMMAND [ARGS] 13 | -n Calculate age as if process was still running 14 | EOF 15 | exit 1 16 | } 17 | 18 | if [ "$1" == -h ] || [ "$1" == --help ] || [ $# -eq 0 ]; then 19 | usage 20 | fi 21 | 22 | if [ "$1" = -n ]; then 23 | now=y 24 | shift 25 | fi 26 | 27 | cmd="$1" 28 | shift 29 | 30 | base_cmd=`basename "$cmd"` 31 | cmd_dir="$AGE_DIR/$base_cmd" 32 | start_file="$cmd_dir/start" 33 | end_file="$cmd_dir/end" 34 | 35 | if ! [ -d "$cmd_dir" ]; then 36 | echo "$cmd_dir does not exist; was the command run under age-track?" >&2 37 | exit 1 38 | fi 39 | 40 | if ! [ -e "$start_file" ]; then 41 | echo "$start_file does not exist; aborting." >&2 42 | exit 1 43 | fi 44 | start=$( cat "$start_file" ) 45 | 46 | if [ -e "$end_file" ]; then 47 | end=$( cat "$end_file" ) 48 | exit=1 # command not running 49 | if [ "$end" -lt "$start" ]; then 50 | echo "Command still running." >&2 51 | end=$( date +"%s" ) 52 | exit=0 53 | fi 54 | else 55 | # no end file, must still be running 56 | echo "Command still running." >&2 57 | end=$( date +"%s" ) 58 | exit=0 59 | fi 60 | 61 | if [ -n "$now" ]; then 62 | end=$( date +"%s" ) 63 | fi 64 | 65 | echo $(( end - start )) 66 | exit $exit 67 | -------------------------------------------------------------------------------- /bin/age-track: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Track the start and end times of a command, ensuring against 4 | # concurrent invocations. Useful as a helper for asynchronous 5 | # process invocations. 6 | 7 | AGE_DIR="$HOME/.run/age" 8 | 9 | me=`basename $0` 10 | 11 | . $ZDOTDIR/lib/libproc.sh 12 | 13 | usage () { 14 | cat <<EOF >&2 15 | Usage: $me [-n NAME] COMMAND [ARGS] 16 | EOF 17 | exit 1 18 | } 19 | 20 | if [ "$1" == -h ] || [ "$1" == --help ] || [ $# -eq 0 ]; then 21 | usage 22 | fi 23 | 24 | if [ "$1" == -n ]; then 25 | name="$2" 26 | shift 2 27 | fi 28 | 29 | cmd="$1" 30 | shift 31 | 32 | base_cmd=`basename "$cmd"` 33 | cmd_dir="$AGE_DIR/${name:-$base_cmd}" 34 | mkdir -p "$cmd_dir" 35 | lock="$cmd_dir/lock" 36 | 37 | clean_up () { 38 | date +"%s" > "$cmd_dir/end" 39 | rm "$lock" || echo "$me: WARNING: rm $lock failed" >&2 40 | } 41 | 42 | obtain_lock "$lock" "$cmd" || exit 1 43 | # Signal must be trapped *after* obtaining lock, otherwise 44 | # failure to obtain the lock would remove an active lock. 45 | trap clean_up EXIT 46 | 47 | echo "$*" > "$cmd_dir/args" 48 | date +"%s" > "$cmd_dir/start" 49 | [ -e "$cmd_dir/exit_code" ] && rm -f "$cmd_dir/exit_code" 50 | 51 | "$cmd" "$@" & 52 | 53 | child_pid=$! 54 | wait $child_pid 55 | 56 | exit=$? 57 | echo $exit > "$cmd_dir/exit_code" 58 | exit $exit 59 | -------------------------------------------------------------------------------- /bin/alertme: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" = '-d' ]; then 4 | text="`date` " 5 | gtext="`date`\n" 6 | shift 7 | else 8 | text= 9 | gtext= 10 | fi 11 | 12 | text="$text$*" 13 | gtext="$gtext$*" 14 | 15 | beep 16 | 17 | if [ -n "$DISPLAY" ]; then 18 | if which zenity >& /dev/null; then 19 | zenity --info --text "$gtext" && exit 0 20 | fi 21 | 22 | if which xmessage >/dev/null 2>&1; then 23 | xmessage "$text" && exit 0 24 | fi 25 | fi 26 | 27 | # getting desperate 28 | echo "$text" | write `id -un` 29 | logger -t "$0[$$]" "$text" 30 | -------------------------------------------------------------------------------- /bin/beep: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Long; 7 | 8 | (my $ME = $0) =~ s,.*/,,; 9 | 10 | sub usage { 11 | warn @_, "\n" if @_; 12 | 13 | die <<EOUSAGE; 14 | Usage: $ME <count> <delay_secs> 15 | Options: 16 | -h, --help Show this help 17 | -v, --verbose[=N] Increase [specify] verbosity (defaults to 1) 18 | EOUSAGE 19 | } 20 | 21 | Getopt::Long::Configure('bundling'); 22 | 23 | my %opts = ( verbosity => 1 ); 24 | GetOptions( 25 | \%opts, 26 | 'help|h', 27 | 'debug|d', 28 | 'verbosity|verbose|v:+', 29 | 'version|V', 30 | ) or usage(); 31 | usage() if @ARGV >= 2 or $opts{help}; 32 | 33 | $| = 1; 34 | 35 | my ($count, $sleep) = @ARGV; 36 | $count ||= 1; 37 | $sleep ||= 1; 38 | 39 | my @sounds_path = qw( 40 | /usr/share/sounds 41 | /usr/share/sounds/gnome/default/alerts 42 | /opt/gnome/share/sounds 43 | /opt/gnome2/share/sounds 44 | /opt/kde3/share/sounds 45 | /opt/kde4/share/sounds 46 | ); 47 | my @sounds = qw( 48 | KDE-Sys-App-Message.ogg 49 | bark.ogg 50 | sonar.ogg 51 | KDE_Beep_Ahem.wav 52 | KDE_Beep_Beep.wav 53 | warning.wav 54 | ); 55 | 56 | sub get_sound_command { 57 | my $sound = find_sound(); 58 | if ($sound) { 59 | my $exe = "paplay"; # FIXME: make more robust 60 | return "$exe \Q$sound\E"; 61 | } 62 | 63 | return 'bip -v 0.1' if `which play 2>&1`; 64 | 65 | die "$ME: couldn't find a way to make a sound!\n"; 66 | } 67 | 68 | sub find_sound { 69 | for my $path (@sounds_path) { 70 | debug(3, "Searching $path"); 71 | for my $sound (@sounds) { 72 | my $full = "$path/$sound"; 73 | if (-r $full) { 74 | debug(2, "Found $full"); 75 | return $full; 76 | } 77 | debug(3, " Skipping unreadable $full"); 78 | } 79 | } 80 | return undef; 81 | } 82 | 83 | while ($count) { 84 | print "\a"; 85 | my $cmd = get_sound_command(); 86 | if ($opts{verbosity} == 0) { 87 | $cmd .= " >/dev/null 2>&1"; 88 | } 89 | elsif ($opts{verbosity} == 1) { 90 | $cmd .= " >/dev/null"; 91 | } 92 | debug(3, "cmd is $cmd"); 93 | system($cmd); 94 | $count--; 95 | sleep $sleep if $count; 96 | } 97 | 98 | sub debug { 99 | my $level = shift; 100 | warn @_, "\n" if $opts{verbosity} >= $level; 101 | } 102 | -------------------------------------------------------------------------------- /bin/bip: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me=`basename $0` 4 | 5 | frequency=440 6 | duration=0.5 7 | volume=0.5 8 | 9 | usage () { 10 | # Call as: usage [EXITCODE] [USAGE MESSAGE] 11 | exit_code=1 12 | if [[ "$1" == [0-9] ]]; then 13 | exit_code="$1" 14 | shift 15 | fi 16 | if [ -n "$1" ]; then 17 | echo "$*" >&2 18 | echo 19 | fi 20 | 21 | cat <<EOF >&2 22 | Usage: $me [options] 23 | Options: 24 | -f, --frequency=FREQUENCY in Hz [$frequency] 25 | -d, --duration=DURATION in seconds [$duration] 26 | -v, --volume=VOLUME as a fraction of 1 [$volume] 27 | EOF 28 | exit "$exit_code" 29 | } 30 | 31 | getopts () { 32 | while [ -n "$1" ]; do 33 | case "$1" in 34 | -h|--help) 35 | usage 0 36 | ;; 37 | -f|--frequency) 38 | frequency="$2" 39 | shift 2 40 | ;; 41 | -d|--duration) 42 | duration="$2" 43 | shift 2 44 | ;; 45 | -v|--volume) 46 | volume="$2" 47 | shift 2 48 | ;; 49 | *) 50 | usage "Unrecognised option: $1" 51 | ;; 52 | esac 53 | done 54 | } 55 | 56 | getopts "$@" 57 | 58 | play -n synth $duration sine $frequency vol $volume >/dev/null 2>&1 59 | -------------------------------------------------------------------------------- /bin/bping: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import argparse 4 | import math 5 | import os 6 | import re 7 | import subprocess 8 | import sys 9 | from textwrap import dedent, wrap 10 | 11 | DEFAULT_VOLUME = 0.05 12 | DEFAULT_DURATION = 0.1 13 | 14 | def parse_args(): 15 | parser = argparse.ArgumentParser( 16 | description = "\n".join(wrap(dedent('''\ 17 | Wrapper around ping to make it do a lot of beeping ;-) 18 | Pitch of beeps represents latency: concert A (440Hz) for 19 | 10ms, going one octave up or down for every order of 20 | magnitude. 21 | '''))), 22 | epilog=epilog(), 23 | formatter_class=argparse.RawDescriptionHelpFormatter, 24 | ) 25 | parser.add_argument('-v', '--volume', metavar='N', type=float, 26 | help='volume of beep [%(default)s]', default = DEFAULT_VOLUME) 27 | parser.add_argument('-d', '--duration', metavar='SECS', type=float, 28 | help='duration of beep [%(default)s]', default = DEFAULT_DURATION) 29 | 30 | if len(sys.argv) < 2: 31 | parser.print_help() 32 | sys.exit(1) 33 | 34 | return parser.parse_known_args() 35 | 36 | def epilog(): 37 | text = 'Guide to conversion of latency to frequency:\n\n' 38 | text += ' %10s %11s\n' % ('Latency', 'Frequency') 39 | text += ' ' + '-' * 19 + '\n' 40 | for latency in (0.01, 0.1, 1, 10, 100, 1000, 10000): 41 | unit = 'ms' 42 | hlatency = latency 43 | if latency >= 1000: 44 | hlatency = latency / 1000 45 | unit = 's' 46 | text += ' %10s %9dHz\n' % (str(hlatency) + unit, frequency(latency)) 47 | return text 48 | 49 | def frequency(latency): 50 | return 440 * 2 ** (math.log10(latency) - 2) 51 | 52 | def bip(frequency, duration, volume): 53 | subprocess.call( 54 | [ 55 | 'bip', 56 | '--volume', str(volume), 57 | '--frequency', str(frequency), 58 | '--duration', str(duration) 59 | ] 60 | ) 61 | 62 | def main(): 63 | options, ping_args = parse_args() 64 | 65 | regexp = re.compile(r'time=(\d+(?:\.\d+)?)\s*(\w+)') 66 | 67 | ping = subprocess.Popen(['ping'] + ping_args, stdin=None, stdout=subprocess.PIPE) 68 | while True: 69 | if ping.poll(): 70 | break 71 | line = ping.stdout.readline().decode() 72 | print(line, end='') 73 | m = regexp.search(line) 74 | if m: 75 | latency, unit = m.groups() 76 | if unit != 'ms': 77 | bip(440, duration=options.duration, volume = options.volume * 2) 78 | raise(RuntimeError, "Unrecognised unit: %s" % unit) 79 | freq = frequency(float(latency)) 80 | bip(freq, options.duration, options.volume) 81 | 82 | main() 83 | -------------------------------------------------------------------------------- /bin/c3: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec cal -3 "$@" 4 | -------------------------------------------------------------------------------- /bin/cg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec chgrp "$@" 4 | -------------------------------------------------------------------------------- /bin/clip: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copy symLink In Place 4 | 5 | me=`basename $0` 6 | 7 | usage () { 8 | # Call as: usage [EXITCODE] [USAGE MESSAGE] 9 | exit_code=1 10 | if [[ "$1" == [0-9] ]]; then 11 | exit_code="$1" 12 | shift 13 | fi 14 | if [ -n "$1" ]; then 15 | echo "$*" >&2 16 | echo 17 | fi 18 | 19 | cat <<EOF >&2 20 | Usage: $me [OPTIONS] SYMLINK [SYMLINK ...] 21 | Options: 22 | -v, --verbose Display successfully converted symlink(s) 23 | -h, --help Show this help 24 | EOF 25 | exit "$exit_code" 26 | } 27 | 28 | if [ "$1" == '-h' ] || [ "$1" == '--help' ] || [ $# == 0 ]; then 29 | usage 0 30 | fi 31 | 32 | verbose= 33 | if [ "$1" == '-v' ] || [ "$1" == '--verbose' ]; then 34 | verbose=y 35 | shift 36 | fi 37 | 38 | main () { 39 | for symlink in "$@"; do 40 | if ! [ -e "$symlink" ]; then 41 | echo "$symlink doesn't exist; skipping." >&2 42 | continue 43 | fi 44 | if ! [ -L "$symlink" ]; then 45 | echo "$symlink not a symlink; skipping." >&2 46 | continue 47 | fi 48 | 49 | copy_symlink_in_place "$symlink" 50 | done 51 | } 52 | 53 | copy_symlink_in_place () { 54 | symlink="$1" 55 | if ! temp=`mktemp "$symlink.$me.XXXXXXXXX"`; then 56 | echo "ERROR: Failed to make temporary file; aborting." >&2 57 | exit 1 58 | fi 59 | if ! cp -p "$symlink" "$temp"; then 60 | echo "ERROR: Failed to copy $symlink to $temp; aborting." >&2 61 | exit 1 62 | fi 63 | if mv "$temp" "$symlink"; then 64 | if [ -n "$verbose" ]; then 65 | echo "$symlink is now a copy of the original symlink target" 66 | fi 67 | else 68 | echo "ERROR: Failed to rename $temp to $symlink; aborting." >&2 69 | exit 1 70 | fi 71 | } 72 | 73 | main "$@" 74 | -------------------------------------------------------------------------------- /bin/cm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | me=cm 6 | mode=`basename $0` 7 | 8 | if [ "$mode" = $me ] && [ -z "$*" ]; then 9 | here=`dirname $0` 10 | echo -n "Setting up handy shortcuts in $here ..." 11 | cd "$here" 12 | for mode in 400 440 444 500 550 555 \ 13 | 600 640 644 664 660 666 \ 14 | {1,2,3,4,}{700,710,711,750,751,755,775,770,771,777} 15 | do 16 | if ! [ -e $mode ]; then 17 | ln -s $me $mode 18 | echo -n " $mode" 19 | fi 20 | done 21 | echo 22 | exit 0 23 | fi 24 | 25 | case "$mode" in 26 | *[0-7]) exec chmod "$mode" "$@" ;; 27 | *) exec chmod "$@" ;; 28 | esac 29 | -------------------------------------------------------------------------------- /bin/colour-diff-output: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | /^cvs server: / { print "\033[1;30m" $0; next } 4 | /^\? / { print "\033[0;33m" $0; next } 5 | /^(Index|======)/ { print "\033[0;1m" $0; next } 6 | /^(diff|RCS file|retrieving)/ { print "\033[0m" $0; next } 7 | /^(@@|\*\*\*(\*| [0-9]+,))/ { print "\033[1;33m" $0; next } 8 | /^(---|\*\*\*) [0-9]+,/ { print "\033[1;33m" $0; next } 9 | /^(---|\+\+\+|\*\*\*) / { print "\033[1;37m" $0; next } 10 | /^-/ { print "\033[0;36m" $0; next } 11 | /^+/ { print "\033[1;32m" $0; next } 12 | /^!/ { print "\033[1;34m" $0; next } 13 | 14 | { print "\033[0m" $0; lines++ } 15 | 16 | END { if (lines > 0) { printf "\033[0m\n" } } 17 | -------------------------------------------------------------------------------- /bin/count-dirents: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $total = 0; 7 | my $multi_mode = @ARGV > 1 ? 1 : 0; 8 | for my $dir (@ARGV) { 9 | if (! opendir(DIR, $dir)) { 10 | warn "Couldn't open $dir: $!; skipping.\n"; 11 | next; 12 | } 13 | 14 | print "$dir " if $multi_mode; 15 | my @dirents = readdir(DIR); 16 | my $count = @dirents - 2; # ignore . and .. 17 | $total += $count; 18 | print "$count\n"; 19 | closedir(DIR); 20 | } 21 | 22 | print "Total $total\n" if $multi_mode; 23 | -------------------------------------------------------------------------------- /bin/cp-merge: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat <<'EOF' >&2 4 | Error: cp-merge has been removed. Consider using rsync with 5 | the following options instead: 6 | 7 | -R, --relative use relative path names 8 | -u, --update skip files that are newer on the receiver 9 | --existing skip creating new files on receiver 10 | --ignore-existing skip updating files that already exist on receiver 11 | --link-dest=DIR hardlink to files in DIR when unchanged 12 | 13 | If hard-linking is required between sources and destination, set 14 | DIR to `pwd` (rsync treats as relative to rsync destination path). 15 | EOF 16 | 17 | exit 1 18 | 19 | -------------------------------------------------------------------------------- /bin/crypt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | openssl passwd "$@" 4 | -------------------------------------------------------------------------------- /bin/csort: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # 3 | # sort(1) helper which allows custom sort orders based on string/regexp matching. 4 | # Prefixes each line with a given value according to whether the line or a field 5 | # within it matches a string or regexp. 6 | 7 | require 'optparse' 8 | require 'open3' 9 | 10 | def parse_options 11 | delimiter = nil 12 | unmatched = "Z" 13 | 14 | parser = OptionParser.new do |opts| 15 | opts.banner = <<EOF 16 | Usage: csort [options] PATTERN VALUE [PATTERN VALUE [...]] 17 | 18 | EOF 19 | opts.on("-t", "--field-separator SEP", String, "set field delimiter [whitespace]") do |d| 20 | delimiter = d 21 | end 22 | opts.on("-u", "--unmatched STR", String, "set unmatched sort value [#{unmatched}]") do |v| 23 | unmatched = v 24 | end 25 | end 26 | 27 | def parser.help # ugh, why doesn't OptionParser allow setting a footer?? 28 | super + <<EOF 29 | 30 | Pattern formats: 31 | /regexp/ - matches if the line contains the (non-anchored) regexp 32 | N:/regexp/ - matches if the Nth field in the line contains the (non-anchored) regexp 33 | N=string - matches if the Nth field in the line is equal to the given string 34 | string - matches if the line is equal to the given string 35 | EOF 36 | end 37 | 38 | parser.parse! 39 | 40 | if ARGV.length == 0 41 | abort "Must have at least one pattern and value." 42 | end 43 | 44 | if ARGV.length % 2 != 0 45 | abort "Each pattern must have a corresponding value." 46 | end 47 | 48 | sort_map = [ ] 49 | (0..ARGV.length-1).step(2).each do |i| 50 | matcher = interpret_pattern(ARGV[i], delimiter) 51 | value = ARGV[i+1] 52 | sort_map.push [matcher, value] 53 | end 54 | 55 | return delimiter, unmatched, sort_map 56 | end 57 | 58 | def interpret_pattern(pattern, delimiter) 59 | case pattern 60 | when %r{^/(.+)/$} 61 | re = Regexp.new($1) 62 | return Proc.new { |line| line =~ re } 63 | when %r{^(\d+):/(.+)/$} 64 | fieldnum = $1.to_i - 1 65 | re = Regexp.new($2) 66 | return Proc.new { |line| 67 | fields = delimiter ? line.split(delimiter) : line.split 68 | fields[fieldnum] =~ re 69 | } 70 | when %r{^(\d+)=(.+)$} 71 | fieldnum = $1.to_i - 1 72 | str = $2 73 | return Proc.new { |line| 74 | fields = delimiter ? line.split(delimiter) : line.split 75 | fields[fieldnum] == str 76 | } 77 | else 78 | return Proc.new { |line| line.chomp == pattern } 79 | #abort "Couldn't interpret pattern '#{pattern}'" 80 | end 81 | end 82 | 83 | def line_prefix(line, sort_map) 84 | sort_map.each do |matcher, value| 85 | return value if matcher.call(line) 86 | end 87 | return nil 88 | end 89 | 90 | def main 91 | delimiter, unmatched, sort_map = parse_options 92 | 93 | $stdin.each_line do |line| 94 | prefix = line_prefix(line, sort_map) || unmatched 95 | puts prefix + (delimiter || ' ') + line 96 | end 97 | end 98 | 99 | main 100 | -------------------------------------------------------------------------------- /bin/cy: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec cal -y "$@" 4 | -------------------------------------------------------------------------------- /bin/dfh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec df -h "$@" 4 | -------------------------------------------------------------------------------- /bin/dfl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec dfll -h "$@" 4 | -------------------------------------------------------------------------------- /bin/dfll: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # df local disk partitions only (excluding tmpfs, loopback mounts etc.) 4 | 5 | exclude="-x none -x tmpfs -x devtmpfs -x iso9660" 6 | 7 | maybe_color () { 8 | if [ -t 1 ]; then 9 | perl -lpe ' 10 | if (/( (\d\d?)% )/) { 11 | my $percent = $2; 12 | my $color = $percent >= 95 ? "41;1" : 13 | $percent >= 90 ? "31" : 14 | $percent >= 80 ? "33" : 15 | $percent >= 50 ? "32" : 16 | "0"; 17 | s/$1/ \e[${color}m${percent}%\e[0m/; 18 | } 19 | ' 20 | else 21 | cat 22 | fi 23 | } 24 | 25 | # When the 1st column gets wide, the remaining columns get split 26 | # onto a separate line. For sorting we need to join them back up. 27 | df -lT $exclude "$@" | 28 | perl -0777pe 's!^(/\S+$)\n!$1!gm; s/Mounted on/Mountedon/' | 29 | column -t | 30 | sed 's/Mountedon/Mounted on/' | 31 | csort \ 32 | 1=Filesystem a \ 33 | 1:/sda/ b \ 34 | 1:/dm-/ c \ 35 | 7=/ d \ 36 | 7=/home e \ 37 | 7:/^\/home/ f \ 38 | 7:/\/mnt/ h \ 39 | 1:/dev\/mapper/ g \ 40 | | 41 | sort -k1,1 -k6,6nr | 42 | cut -c3- | 43 | maybe_color 44 | -------------------------------------------------------------------------------- /bin/diff-less: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | less +/'^(\[1;37m)?--- 4 | jjg' "$@" 5 | -------------------------------------------------------------------------------- /bin/div: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # divider - useful in a pipeline to separate output 4 | 5 | width="${COLUMNS:-72}" 6 | if [ "$1" = '-n' ]; then 7 | no_blank_lines=t 8 | shift 9 | fi 10 | char="${1:->}" 11 | 12 | divider= 13 | for (( i=1; i<=width; i++)); do 14 | divider="$divider$char" 15 | done 16 | 17 | [ -n "$no_blank_lines" ] || echo 18 | echo "$divider" 19 | [ -n "$no_blank_lines" ] || echo 20 | -------------------------------------------------------------------------------- /bin/dl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -t 1 ]; then 4 | # connected to a tty => make it fit for human consumption 5 | opts=--expand-tabs 6 | fi 7 | 8 | exec diff -u $opts "$@" | tty-colour-diff 9 | -------------------------------------------------------------------------------- /bin/dts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # dts - runs a command, date/time-stamping each line of STDOUT 4 | # 5 | # Understands a single optional argument for the type of format to use. 6 | # l => localtime long format - DEFAULT 7 | # g => gmtime long format, e.g. 2003/09/05 09:52:17.139092 8 | # a => absolute seconds 9 | # 10 | # See also ts from moreutils which does pretty much the same thing: 11 | # http://git.kitenet.net/?p=moreutils.git;a=blob;f=ts;hb=HEAD 12 | 13 | use strict; 14 | use warnings; 15 | 16 | use Date::Calc 'Day_of_Week_Abbreviation'; 17 | use Getopt::Long; 18 | use Time::HiRes; 19 | 20 | $| = 1; # turn output buffering off 21 | 22 | (my $ME = $0) =~ s,.*/,,; 23 | 24 | my %opts = (); 25 | Getopt::Long::Configure('bundling', 'passthrough'); 26 | GetOptions( 27 | \%opts, 28 | 'help|h', 29 | 'gmtime|g', 'epoch|e', 'usec|u', 30 | ) or usage(); 31 | usage() if $opts{help}; 32 | 33 | sub usage { 34 | warn @_, "\n" if @_; 35 | 36 | die <<EOUSAGE; 37 | Usage: $ME [options] COMMAND [ARGS...] 38 | If COMMAND is omitted, acts as a STDIN filter instead. 39 | Options: 40 | -h, --help Show this help 41 | -g, --gmtime Use UTC not local time 42 | -e, --epoch Show seconds since UNIX epoch 43 | -u, --usec Show microseconds 44 | EOUSAGE 45 | } 46 | 47 | my $printformat = "%04d/%02d/%02d %3s %02d:%02d:%02d"; 48 | $printformat .= ".%06d" if $opts{usec}; 49 | $printformat .= " "; 50 | 51 | open(CMD, @ARGV ? "@ARGV |" : "<&STDIN") or die $!; 52 | while(<CMD>) { 53 | my ($seconds, $usec) = Time::HiRes::gettimeofday(); 54 | if ($opts{epoch}) { 55 | print $seconds . "." . $usec . " " . $_; 56 | } 57 | else { 58 | my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) 59 | = $opts{gmtime} ? gmtime($seconds) : localtime($seconds); 60 | printf $printformat, 61 | 1900 + $year, 62 | $mon + 1, 63 | $mday, 64 | Day_of_Week_Abbreviation($wday || 7), 65 | $hour, 66 | $min, 67 | $sec, 68 | $opts{usec} ? $usec : (); 69 | print; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /bin/du1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # du1 (du with depth 1) 4 | 5 | du --max-depth=1 "$@" 6 | #du "$@" | egrep -v '/.*/' 7 | 8 | # Another idea from Bart Schaefer, which I need to fix 9 | # to take parameters 10 | #du -s *(/) 11 | -------------------------------------------------------------------------------- /bin/du2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # du2 (du with depth 2) 4 | # see also du1 5 | 6 | du --max-depth=2 "$@" 7 | -------------------------------------------------------------------------------- /bin/dump-inodes: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | if [ $# != 1 ]; then 4 | echo "Usage: $0 DIR" >&2 5 | fi 6 | 7 | if ! cd "$1"; then 8 | echo "Failed to cd to $1" >&2 9 | exit 1 10 | fi 11 | 12 | # Try to avoid crappy broken pipe errors when piping through head etc. 13 | 14 | # Bah, this hangs it 15 | #trap '' PIPE 16 | 17 | nop () { 18 | : 19 | exit 0 20 | } 21 | # this doesn't work either 22 | trap nop PIPE 23 | 24 | # line-based output format 25 | echo '# file:user:uid:group:gid:mode:atime:ctime:mtime' 26 | find . -printf "%p:%u:%U:%g:%G:%m:%A@:%C@:%T@\n" 27 | 28 | # paragraph-based output format 29 | #find . -printf "file %p\nuser %u\nuid %U\ngroup %g\ngid %G\nmode %m\natime %A@\nctime %C@\nmtime %T@\n\n" 30 | -------------------------------------------------------------------------------- /bin/dumpenv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # This is more readable than the devilishly cunning winner of an old 4 | # obfuscated Perl competition: 5 | # 6 | # perl -0l12pe1 /proc/$pid/environ 7 | 8 | import sys 9 | 10 | pid = sys.argv[1] 11 | 12 | with open("/proc/%s/environ" % pid) as f: 13 | for line in f.readline().split("\0"): 14 | if line: 15 | print(line) 16 | -------------------------------------------------------------------------------- /bin/dutree: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # dutree - print sorted indented rendition of du output 3 | use strict; 4 | 5 | my %Dirsize; 6 | my %Kids; 7 | 8 | getdots(my $topdir = input()); 9 | output($topdir); 10 | 11 | # run du, read in input, save sizes and kids 12 | # return last directory (file?) read 13 | sub input { 14 | my($size, $name, $parent); 15 | @ARGV = ("du @ARGV |"); # prep the arguments 16 | while (<>) { # magic open is our friend 17 | ($size, $name) = split; 18 | $Dirsize{$name} = $size; 19 | ($parent = $name) =~ s#/[^/]+$##; # dirname 20 | push @{ $Kids{$parent} }, $name unless eof; 21 | } 22 | return $name; 23 | } 24 | 25 | # figure out how much is taken up in each directory 26 | # that isn't stored in subdirectories. add a new 27 | # fake kit called "." containing that much. 28 | sub getdots { 29 | my $root = $_[0]; 30 | my($size, $cursize); 31 | $size = $cursize = $Dirsize{$root}; 32 | if ($Kids{$root}) { 33 | for my $kid (@{ $Kids{$root} }) { 34 | $cursize -= $Dirsize{$kid}; 35 | getdots($kid); 36 | } 37 | } 38 | if ($size != $cursize) { 39 | my $dot = "$root/."; 40 | $Dirsize{$dot} = $cursize; 41 | push @{ $Kids{$root} }, $dot; 42 | } 43 | } 44 | 45 | # recursively output everything, 46 | # passing padding and number width in as well 47 | # on recursive calls 48 | sub output { 49 | my($root, $prefix, $width) = (shift, shift || '', shift || 0); 50 | my $path; 51 | ($path = $root) =~ s#.*/##; # basename 52 | my $size = $Dirsize{$root}; 53 | my $line = sprintf("%${width}d %s", $size, $path); 54 | print $prefix, $line, "\n"; 55 | for ($prefix .= $line) { # build up more output 56 | s/\d /| /; 57 | s/[^|]/ /g; 58 | } 59 | if ($Kids{$root}) { # not a bachelor node 60 | my @Kids = @{ $Kids{$root} }; 61 | @Kids = sort { $Dirsize{$b} <=> $Dirsize{$a} } @Kids; 62 | $Dirsize{$Kids[0]} =~ /(\d+)/; 63 | my $width = length $1; 64 | for my $kid (@Kids) { output($kid, $prefix, $width) } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /bin/edate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # epoch date 4 | 5 | if [ -n "$1" ]; then 6 | date +%s -d "$*" 7 | else 8 | date +%s 9 | fi 10 | 11 | -------------------------------------------------------------------------------- /bin/fbig: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Find big files 4 | 5 | if [ -t 0 ]; then 6 | exec ls -alFR "$@" | grep '^-' | sort -rn -k5 | less -r 7 | else 8 | # assume we're filtering output from find -ls 9 | sort -nr -k7 | less 10 | fi 11 | -------------------------------------------------------------------------------- /bin/fds: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec file-datestamp "$@" 4 | -------------------------------------------------------------------------------- /bin/fdst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | fds -t 4 | -------------------------------------------------------------------------------- /bin/feed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # Feed keystrokes to a command then interact with it as normal. 4 | # 5 | # $Id$ 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use Expect; 11 | use FindBin '$RealScript'; 12 | use Getopt::Long; 13 | 14 | use Sh 'qqexpand'; 15 | 16 | my %opts; 17 | Getopt::Long::Configure('require_order'); 18 | GetOptions(\%opts, 'command=s') 19 | or usage(); 20 | @ARGV or usage(); 21 | 22 | sub usage { 23 | die "Usage: $RealScript -c 'text to feed' command [arg1 [arg2 ...]]\n"; 24 | } 25 | 26 | my $exp = new Expect; 27 | $exp->slave->clone_winsize_from(\*STDIN); 28 | $exp->spawn(@ARGV) or die "Cannot spawn $ARGV[0]: $!\n"; 29 | sleep 1; 30 | $exp->send(qqexpand($opts{command})); 31 | $exp->interact; 32 | 33 | -------------------------------------------------------------------------------- /bin/file-datestamp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # avoid using : in the filename as will break usage within 4 | # $PATH etc., also in NFS automounts according to the Hickster. 5 | 6 | usage () { 7 | if [ -n "$1" ]; then 8 | echo "$*" >&2 9 | echo 10 | fi 11 | 12 | me=`basename $0` 13 | 14 | cat <<EOF >&2 15 | Usage: $me [-p] [-t] 16 | Default format: YYYY-MM-DD 17 | Options: 18 | -p Path format: YYYY/MM/DD 19 | -t Append time: -HHMMhSS (or /HHMMhSS if with -p) 20 | EOF 21 | exit 1 22 | } 23 | 24 | format="%Y-%m-%d" # Equivalent to %F, the ISO 8601 date format. 25 | 26 | while [ -n "$1" ]; do 27 | case "$1" in 28 | -p) 29 | format="%Y/%m/%d" 30 | path=y 31 | shift 32 | ;; 33 | -t) 34 | timestamp=y 35 | shift 36 | ;; 37 | *) 38 | usage 39 | ;; 40 | esac 41 | done 42 | 43 | if [ -n "$timestamp" ]; then 44 | if [ -n "$path" ]; then 45 | format="$format/%H%Mh%Ss" 46 | else 47 | format="$format-%H%Mh%Ss" 48 | fi 49 | fi 50 | 51 | date +"$format" 52 | -------------------------------------------------------------------------------- /bin/find-wan-gateway: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if traceroute news.bbc.co.uk 2>&1 | awk '/^ *2 /{print $2;exit 0}'; then 4 | exit 0 5 | fi 6 | 7 | exit 1 8 | 9 | -------------------------------------------------------------------------------- /bin/fs-monitor: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | me=`basename $0` 4 | 5 | usage () { 6 | cat <<EOF >&2 7 | Usage: $me [options] FILESYSTEM DELAY 8 | EOF 9 | exit 1 10 | } 11 | 12 | if [ "$1" == -h ] || [ "$1" == --help ] || [ $# != 2 ]; then 13 | usage 14 | fi 15 | 16 | fs="$1" 17 | delay="$2" 18 | 19 | while true; do 20 | echo -n "`edate`" 21 | df . | grep $fs 22 | sleep $delay 23 | done 24 | -------------------------------------------------------------------------------- /bin/fswap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # swap the names of two files 4 | 5 | if [ $# != 2 ]; then 6 | echo "Usage: $0 <file1> <file2>" 7 | exit 1 8 | fi 9 | 10 | if ! mv -i "$1" "$1.fswap.tmp.$$"; then 11 | echo "Failed to mv $1 $1.fswap.tmp.$$ ! Aborting." 12 | exit 1 13 | fi 14 | 15 | if ! mv -i "$2" "$1"; then 16 | echo "Failed to mv $2 $1 ! Restoring $1." 17 | if ! mv -i "$1.fswap.tmp.$$" "$1"; then 18 | echo "Failed to restore $1 !!" 19 | fi 20 | exit 1 21 | fi 22 | 23 | if ! mv -i "$1.fswap.tmp.$$" "$2"; then 24 | echo "Failed to mv $1.fswap.tmp.$$ to $2 !" 25 | exit 1 26 | fi 27 | -------------------------------------------------------------------------------- /bin/ftrace: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if which strace 2>&1 >/dev/null; then 3 | strace -e trace=file "$@" 4 | else 5 | echo "strace not found" >&2 6 | exit 1 7 | fi 8 | -------------------------------------------------------------------------------- /bin/glob-to-re: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Filter to convert globs into regexps 4 | # e.g. glob-to-re ~/.cvsignore 5 | 6 | use Sh qw(glob_to_unanchored_re glob_to_anchored_re); 7 | use Getopt::Long; 8 | 9 | Getopt::Long::Configure('bundling'); 10 | 11 | my %opts = ( verbosity => 1 ); 12 | GetOptions( 13 | \%opts, 14 | 'help|h', 15 | 'unanchored|u', 16 | ) or usage(); 17 | usage() if @ARGV > 1 or $opts{help}; 18 | 19 | sub usage { 20 | warn @_, "\n" if @_; 21 | 22 | (my $ME = $0) =~ s,.*/,,; 23 | 24 | die <<EOUSAGE; 25 | Usage: $ME options 26 | Options: 27 | -h, --help Show this help 28 | -u, --unanchored Don't anchor the regexps 29 | options2 30 | EOUSAGE 31 | } 32 | 33 | while (<>) { 34 | print, next if /^\s*(#|$)/; 35 | print $opts{unanchored} ? glob_to_unanchored_re($_): glob_to_anchored_re($_); 36 | } 37 | -------------------------------------------------------------------------------- /bin/grep-shortcuts: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me="grep-shortcuts" 4 | mode=`basename $0` 5 | 6 | if [ "$mode" = "$me" ] && [ -z "$*" ]; then 7 | here=`dirname $0` 8 | if [ -z "$ZDOTDIR" ]; then 9 | echo "\$ZDOTDIR not set; aborting." >&2 10 | exit 1 11 | fi 12 | 13 | echo -n "Setting up handy grep shortcuts in $here ..." 14 | cd "$here" 15 | # see also global aliases in .zshrc 16 | for switches in '' {,i}{,l,L}{,r,R}{,v}{,C}; do 17 | cmd=g$switches 18 | preexisting=$( which $cmd 2>/dev/null ) 19 | if [ $? = 0 ] && [ "$ZDOTDIR/bin/$cmd" != "$preexisting" ]; then 20 | echo -ne "\nWARNING! $cmd already found on path" >&2 21 | fi 22 | if ! [ -e $cmd ]; then 23 | ln -s $me $cmd 24 | echo -n " $cmd" 25 | fi 26 | done 27 | echo 28 | exit 0 29 | fi 30 | 31 | switches="${mode#g}" 32 | color= 33 | case "$switches" in 34 | *C*) 35 | switches="${switches//C/}" 36 | color=--color=always 37 | ;; 38 | esac 39 | 40 | [ -n "$switches" ] && switches=-$switches 41 | 42 | exec egrep $switches $color "$@" 43 | -------------------------------------------------------------------------------- /bin/gse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/zsh 2 | 3 | # gse (Grep Shell-Env) - greps my various shell-env files 4 | 5 | lse | xargs egrep "$@" 6 | -------------------------------------------------------------------------------- /bin/gw-IP: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ip route | awk '/^default via/ { print $3 }' 4 | -------------------------------------------------------------------------------- /bin/gw-dev: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | gw-devs | head -n 1 4 | -------------------------------------------------------------------------------- /bin/gw-dev-IP: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Note ifplugstatus could also be useful on SUSE systems. 4 | 5 | if ! gwdev="`gw-dev`" || [ -z "$gwdev" ]; then 6 | echo "gw-dev failed to return gateway device; aborting." >&2 7 | exit 1 8 | fi 9 | 10 | ip addr show "$gwdev" | \ 11 | perl -lne 'if (/ inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) { print $1; exit 0 }' 12 | -------------------------------------------------------------------------------- /bin/gw-devs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ip route | ruby -lne 'puts $1 if /^default .* dev (\S+)/' 4 | -------------------------------------------------------------------------------- /bin/harden-ln: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # Reads symlinks from @ARGV and/or STDIN 4 | # and converts them to hard links. 5 | # 6 | 7 | use strict; 8 | use warnings; 9 | 10 | use Cwd; 11 | use File::Basename; 12 | use File::Copy; 13 | use Getopt::Long; 14 | 15 | (my $me = $0) =~ s,.*/,,; 16 | 17 | my %opts; 18 | GetOptions(\%opts, 'help|h', 'test|t', 'copy|c') or usage(); 19 | usage() if $opts{help}; 20 | 21 | sub usage { 22 | die <<EOUSAGE; 23 | Usage: $me [options] [symlink1 [symlink 2 ...] | [ < symlink-file ] ] 24 | Options: 25 | -t, --test See what would have happened. 26 | -c, --copy Make copies instead of hard links. 27 | 28 | Takes a list of symlinks from arguments and/or STDIN (one per line) 29 | and converts them to hard links or copies. 30 | EOUSAGE 31 | } 32 | 33 | my @links = @ARGV; 34 | if (! @ARGV && ! -t 0) { 35 | while (<STDIN>) { 36 | chomp; 37 | s/^\s+//; 38 | s/\s+$//; 39 | push @links, $_; 40 | } 41 | } 42 | 43 | my $start_dir = cwd(); 44 | harden($_) foreach @links; 45 | 46 | sub harden { 47 | my ($link) = @_; 48 | 49 | chdir($start_dir) or die "chdir($start_dir) failed: $!\n"; 50 | 51 | unless (-l $link) { 52 | warn "$link not a symlink; skipping.\n"; 53 | return; 54 | } 55 | 56 | my $dest = readlink $link or die "$me: readlink($link): $!\n"; 57 | 58 | if ($opts{test}) { 59 | print "Would ", $opts{copy} ? 'copy' : 'harden', " $link\n"; 60 | return; 61 | } 62 | 63 | unlink $link or die "$me: unlink($link): $!\n"; 64 | 65 | my $link_dir = dirname($link); 66 | my $link_file = basename($link); 67 | chdir($link_dir) or die "chdir($link_dir) failed: $!\n"; 68 | return if $opts{copy} ? copy($dest, $link_file) : link($dest, $link_file); 69 | warn "$me: ", $opts{copy} ? 'copy' : 'link', 70 | "($dest, $link) failed: $!\n"; 71 | 72 | symlink($dest, $link_file) 73 | or warn "$me: WARNING! Couldn't restore symlink $link -> $dest ", 74 | "after hardening failed ($!)\n"; 75 | } 76 | -------------------------------------------------------------------------------- /bin/hex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | output_hex(@ARGV); 7 | @ARGV = (); 8 | if (! -t) { 9 | while (<>) { 10 | output_hex($_); 11 | } 12 | } 13 | 14 | sub output_hex { 15 | printf "%x\n", $_ foreach @_; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /bin/host-has-prop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me=$(basename $0) 4 | 5 | if [ $# != 1 ]; then 6 | echo >&2 "Usage: $me PROP" 7 | exit 1 8 | fi 9 | 10 | grep -q "^$1\$" ~/.localhost-props 11 | -------------------------------------------------------------------------------- /bin/icmp-blocked: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # N.B. some fuckwit ISPs block ICMP, so watch out for those 4 | # and hope for the best. 5 | nmcli | \ 6 | egrep -iq 'connected to (Avanti_Free_WiFi)' 7 | -------------------------------------------------------------------------------- /bin/ifw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ip addr show "$@" 2>&1 | \ 4 | perl -0777pe 's/^\d+: (lo|v(eth|net)\d+):\s[^\n]+\n( [^\n]+\n)+//gms; 5 | s/^\s+.*(valid_lft|forever).*\n//gm' 6 | 7 | which iwconfig >& /dev/null && \ 8 | iwconfig "$@" 2>&1 | \ 9 | perl -0777pe 's/.*\sno wireless extensions.*\n\n//g; 10 | s/.*(RTS|[RT]x invalid|excessive retries).*\n//g; 11 | s/\n+$/\n/;' 12 | 13 | echo 14 | rj 'dhc|(ipw|iwl)3945|wpa_' 15 | echo 16 | lsof -i udp:bootpc 17 | -------------------------------------------------------------------------------- /bin/isup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PING_COUNT=10 4 | 5 | me=`basename $0` 6 | 7 | usage () { 8 | cat <<EOF >&2 9 | Usage: $me HOSTNAME 10 | EOF 11 | exit 1 12 | } 13 | 14 | if [ "$1" == '-h' ] || [ "$1" == '--help' ] || [ $# != 1 ]; then 15 | usage 16 | fi 17 | 18 | host="$1" 19 | shift 20 | 21 | host_up= 22 | case "$OSTYPE" in 23 | solaris*) 24 | echo "FIXME: ping count option?" >&2 25 | exit 1 26 | # redirect stderr to avoid "no route to host" type errors 27 | ping -s "$host" 2>&1 | grep -q 'bytes from' && host_up=yes 28 | ;; 29 | 30 | # FreeBSD and Linux 31 | *) 32 | ping -c "$PING_COUNT" -w "$PING_COUNT" "$host" 2>&1 | \ 33 | grep -q 'bytes from' && host_up=yes 34 | ;; 35 | esac 36 | 37 | if [ -n "$host_up" ]; then 38 | exit 0 39 | else 40 | exit 1 41 | fi 42 | -------------------------------------------------------------------------------- /bin/jc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | journalctl "$@" 4 | -------------------------------------------------------------------------------- /bin/jcf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | journalctl -f "$@" 4 | -------------------------------------------------------------------------------- /bin/jcf2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | journalctl -f --since="2 days ago" "$@" 4 | -------------------------------------------------------------------------------- /bin/jcfu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | jcf --unit "$@" 4 | -------------------------------------------------------------------------------- /bin/jl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # FIXME: the nice lnavf behaviour doesn't work because jcf takes a 4 | # while to spew log history down the pipe, and lnav has no way of 5 | # knowing when it's done. 6 | jcf2 "$@" | lnavf 7 | -------------------------------------------------------------------------------- /bin/jlu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | jl --unit "$@" 4 | -------------------------------------------------------------------------------- /bin/keepalive: -------------------------------------------------------------------------------- 1 | #!/opt/perl-5.6.1/bin/perl 2 | # 3 | # Keep an ssh session alive (for port forwarding). Not sure whether 4 | # this is actually of use, since it's tocket's java app TCP connection 5 | # which needs to be kept alive and that's done via shiver-pointer on 6 | # the client WM. 7 | # 8 | # $Id$ 9 | 10 | use strict; 11 | use warnings; 12 | 13 | my $ESCAPE = '~@@'; 14 | 15 | use lib '/home/lonlxadm/lib/perl5'; 16 | 17 | use FindBin '$RealScript'; 18 | use Getopt::Long; 19 | 20 | use lib '/home/aspiers/lib/perl5'; 21 | use Expect; 22 | 23 | @ARGV or usage(); 24 | 25 | sub usage { 26 | die <<EOF; 27 | Usage: $RealScript connect-command [arg1 [arg2 ...]] 28 | Connect to remote site, get a prompt, then hit $ESCAPE 29 | EOF 30 | } 31 | 32 | my $exp = new Expect; 33 | $exp->slave->clone_winsize_from(\*STDIN); 34 | #$exp->slave->stty(qw(raw -echo)); 35 | $exp->log_user(0); 36 | 37 | $exp->spawn(@ARGV) or die "Cannot spawn $ARGV[0]: $!\n"; 38 | 39 | print "Login and get a prompt, then hit $ESCAPE\n"; 40 | $exp->interact(\*STDIN, $ESCAPE); 41 | print "\nEscape received; switching to keepalive mode.\n"; 42 | 43 | # Send a control-U to cancel escape sequence 44 | $exp->send("\cu\n"); 45 | $exp->expect(1, "\n"); # flush expect queue 46 | $exp->send("cat > /dev/null\n"); 47 | $exp->expect(1, "\n"); # flush expect queue 48 | #$exp->expect(0); 49 | 50 | my $mins = 0; 51 | while (1) { 52 | $exp->send("$mins minute" . ($mins == 1 ? '' : 's') . " of keepalive; press C-c to disconnect\n"); 53 | sleep 1; # yuk 54 | $exp->expect(1, "\n"); # flush expect queue 55 | sleep 60; 56 | $mins++; 57 | } 58 | -------------------------------------------------------------------------------- /bin/lesspipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh - 2 | # 3 | # To use this filter with less, define LESSOPEN: 4 | # export LESSOPEN="|~/bin/lesspipe.sh %s" 5 | 6 | lesspipe() { 7 | case "$1" in 8 | *.[1-9n]|*.man|*.[1-9n].bz2|*.man.bz2|*.[1-9].gz|*.[1-9]x.gz|*.[1-9].man.gz) 9 | case "$1" in 10 | *.gz) DECOMPRESSOR="gunzip -c" ;; 11 | *.bz2) DECOMPRESSOR="bunzip2 -c" ;; 12 | *) DECOMPRESSOR="cat" ;; 13 | esac 14 | if $DECOMPRESSOR -- "$1" | file - | grep -q troff; then 15 | if echo "$1" | grep -q ^/; then #absolute path 16 | man -- "$1" | cat -s 17 | else 18 | man -- "./$1" | cat -s 19 | fi 20 | else 21 | $DECOMPRESSOR -- "$1" 22 | fi 23 | ;; 24 | *.tar|*.gem) 25 | tar tvvf "$1" 26 | ;; 27 | *.tgz|*.tar.gz|*.tar.[zZ]|*.box) 28 | tar tzvvf "$1" 29 | ;; 30 | *.tar.bz2|*.tbz|*.tbz2) 31 | tar jtvvf "$1" 32 | ;; 33 | *.tar.xz|*.txz) 34 | tar Jtvvf "$1" 35 | ;; 36 | *initrd*.gz) 37 | gunzip -c "$1" | cpio -tv 38 | ;; 39 | *.[zZ]|*.gz|*.svgz) 40 | gzip -dc -- "$1" 41 | ;; 42 | *.bz2) 43 | bzip2 -dc -- "$1" 44 | ;; 45 | *.7z) 46 | 7z l "$1" 47 | ;; 48 | *.xz) 49 | xz -dc -- "$1" 50 | ;; 51 | *.zip|*.Zip|*.ZIP|*.jar|*.war|*.sar|*.xpi|*.job|*.pylib|*.apk|*.egg) 52 | zipinfo -- "$1" 53 | ;; 54 | *.rar) 55 | unrar v "$1" 56 | ;; 57 | *.[rs]pm) 58 | rq "$1" 59 | ;; 60 | *.cpi|*.cpio|*.obscpio) 61 | cpio -itv < "$1" 62 | ;; 63 | *.htm|*.html) 64 | exec w3m -T text/html "$1" 65 | ;; 66 | *.gif|*.jpeg|*.jpg|*.pcd|*.png|*.tga|*.tiff|*.tif) 67 | if [ -x "`which identify`" ]; then 68 | identify "$1" 69 | else 70 | echo "No identify available" 71 | echo "Install ImageMagick to browse images" 72 | fi 73 | ;; 74 | *) 75 | case "$1" in 76 | *.gz) DECOMPRESSOR="gunzip -c" ;; 77 | *.bz2) DECOMPRESSOR="bunzip2 -c" ;; 78 | esac 79 | if [ ! -z $DECOMPRESSOR ] ; then 80 | $DECOMPRESSOR -- "$1" ; 81 | fi 82 | ;; 83 | # Can't remember why I wanted to allow use as a filter but it breaks 84 | # hitting 'v' from less to edit. 85 | # *) cat "$1" ;; 86 | esac 87 | } 88 | 89 | lesspipe "$1" 2>/dev/null 90 | -------------------------------------------------------------------------------- /bin/lh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec last "$@" | head -20 4 | -------------------------------------------------------------------------------- /bin/lnav2: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # 3 | # Wrapper around lnav which adds some handy extra options. 4 | 5 | require 'time' 6 | require 'optparse' 7 | require 'optparse/time' 8 | require 'pp' 9 | 10 | ENV['LANG'] = "C" 11 | 12 | class OptionParser 13 | # Like order!, but leave any unrecognized --switches alone 14 | # https://stackoverflow.com/a/40434335/179332 15 | def order_recognized!(args=ARGV) 16 | extra_opts = [] 17 | begin 18 | order!(args) { |a| extra_opts << a } 19 | rescue OptionParser::InvalidOption => e 20 | extra_opts << e.args[0] 21 | retry 22 | end 23 | args[0, 0] = extra_opts 24 | end 25 | end 26 | 27 | def main 28 | options = parse_options 29 | 30 | args = [ 31 | # hack to make r/R hotkeys default to navigating one minute forward/back 32 | # https://github.com/tstack/lnav/issues/382 33 | "-c", ":goto 1 min later", 34 | ] 35 | 36 | if options[:hide_before] 37 | args += [ "-c", ":hide-lines-before +#{options[:hide_before]}" ] 38 | end 39 | 40 | if options[:start_at] 41 | args += [ "-c", ":goto +#{options[:start_at]}" ] 42 | else 43 | # put first error in middle of display 44 | args += [ 45 | '-c', ':goto 0', 46 | '-c', ':next-mark error', 47 | '-c', ':relative-goto -20', 48 | ] 49 | end 50 | 51 | args += ARGV 52 | 53 | puts "Running lnav with args:" 54 | args.each { |arg| puts " " + arg.inspect } 55 | 56 | system 'lnav', *args 57 | end 58 | 59 | def parse_options 60 | {}.tap do |options| 61 | parser = OptionParser.new do |opts| 62 | opts.banner = "Usage: #$0 [options] [args]" 63 | 64 | opts.on("-h", "--help", "Show this help") do 65 | puts parser 66 | puts "\nOther options and arguments are passed on to lnav:\n\n" 67 | system "lnav", "-h" 68 | exit 69 | end 70 | 71 | opts.on("--hide-before TIME", Time, "Hide lines before TIME") do |time| 72 | options[:hide_before] = time.strftime("%s") 73 | end 74 | 75 | opts.on("--start-at TIME", Time, "Start viewing at TIME") do |time| 76 | options[:start_at] = time.strftime("%s") 77 | end 78 | end 79 | 80 | parser.order_recognized! 81 | end 82 | end 83 | 84 | main 85 | -------------------------------------------------------------------------------- /bin/lnave: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # lnav with jumping to last line 4 | 5 | # By default, lnav2 does this for us 6 | exec lnav2 "$@" 7 | -------------------------------------------------------------------------------- /bin/lnavf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | lnav \ 4 | -q \ 5 | "$@" \ 6 | -c ':goto -1' \ 7 | -c ':mark' \ 8 | -c ':goto -30' \ 9 | -------------------------------------------------------------------------------- /bin/ls-sparse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Long; 7 | 8 | Getopt::Long::Configure('bundling'); 9 | 10 | sub usage { 11 | warn @_, "\n" if @_; 12 | 13 | (my $ME = $0) =~ s,.*/,,; 14 | 15 | die <<EOUSAGE; 16 | Usage: $ME FILE1 [FILE2 ...] 17 | Options: 18 | --help Show this help 19 | -h, --human-readable Show sizes in kB, MB, GB etc. 20 | -s, --sparse-only Only show sparse files 21 | -n, --nonsparse-only Only show non-sparse files 22 | -p, --path Only show filename path (with -s or -n) 23 | EOUSAGE 24 | } 25 | 26 | my %opts = ( verbosity => 1 ); 27 | GetOptions( 28 | \%opts, 29 | 'help', 30 | 'human-readable|h', 31 | 'sparse-only|s', 32 | 'nonsparse-only|n', 33 | 'path|p', 34 | ) or usage(); 35 | usage() if @ARGV == 0 or $opts{help}; 36 | usage("--sparse-only and --nonsparse-only are mutually exclusive.\n") 37 | if $opts{'sparse-only'} && $opts{'nonsparse-only'}; 38 | usage("--path requires --sparse-only or --nonsparse-only.\n") 39 | if $opts{path} && ! $opts{'sparse-only'} && ! $opts{'nonsparse-only'}; 40 | usage("--human-readable and --path are mutually exclusive.\n") 41 | if $opts{'human-readable'} && $opts{'path'}; 42 | 43 | if ($opts{'human-readable'}) { 44 | eval { require Number::Bytes::Human; }; 45 | usage("Need Number::Bytes::Human CPAN module installed for --human-readable.\n") 46 | if $@; 47 | Number::Bytes::Human->import(qw(format_bytes)); 48 | } 49 | 50 | if (! $opts{path}) { 51 | if ($opts{'human-readable'}) { 52 | print " size alloc saved sparse file\n"; 53 | } 54 | else { 55 | print " size alloc saved sparse file\n"; 56 | } 57 | } 58 | 59 | foreach my $file (@ARGV) { 60 | check($file); 61 | } 62 | 63 | sub check { 64 | my ($file) = @_; 65 | my @stat = stat $file or die "stat($file) failed: $!\n"; 66 | my ($size, $blocks) = @stat[7, 12]; 67 | # $size includes unallocated blocks which are nominally "in use" 68 | # but actually full of zeros so not stored on disk. 69 | my $allocated = $blocks*512; 70 | my $sparseness = $size ? $allocated / $size : 1; 71 | # Note sparseness of exactly 1 happens when every byte of the 72 | # allocated blocks have been used, i.e. with non-sparse files. 73 | # Therefore non-sparse files will have a value >= 1, and sparse 74 | # files will have a value < 1. 75 | my $sparse = $allocated < $size; 76 | return if $opts{ 'sparse-only'} && ! $sparse; 77 | return if $opts{'nonsparse-only'} && $sparse; 78 | 79 | my $saved = $size - $allocated; 80 | if ($opts{'human-readable'}) { 81 | printf "%5s %5s %6s %6.2f %s\n", 82 | format_bytes($size), 83 | format_bytes($allocated), 84 | format_bytes($saved), 85 | $sparseness, 86 | $file; 87 | } 88 | elsif ($opts{path}) { 89 | print "$file\n"; 90 | } 91 | else { 92 | printf "%11d %11d %11d %6.2f %s\n", 93 | $size, 94 | $allocated, 95 | $saved, 96 | $sparseness, 97 | $file; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /bin/lse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/zsh 2 | 3 | # lse (List Shell-Env) - lists my various shell-env files 4 | 5 | # N.B. search $ZODTIDR not the git repos, since there might be unstowed 6 | # files in there which we want to search too. 7 | 8 | paths=( 9 | $ZDOTDIR/.profile 10 | $ZDOTDIR/.bashenv* 11 | $ZDOTDIR/.bash_profile 12 | $ZDOTDIR/.bashrc* 13 | $ZDOTDIR/.zlogin 14 | $ZDOTDIR/.zprofile 15 | $ZDOTDIR/.zshenv* 16 | $ZDOTDIR/.zshrc* 17 | $ZDOTDIR/.zsh 18 | $ZDOTDIR/.shared* 19 | ) 20 | 21 | sfind ${^paths}(N) 22 | -------------------------------------------------------------------------------- /bin/lsofp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me=`basename $0` 4 | 5 | usage () { 6 | cat <<EOF >&2 7 | Usage: $me <proc> [<lsof_args>] 8 | proc is substring to pass to pgrep 9 | EOF 10 | exit 1 11 | } 12 | 13 | if [ "$1" == '-h' ] || [ "$1" == '--help' ] || [ -z "$1" ]; then 14 | usage 15 | fi 16 | 17 | proc="$1" 18 | shift 19 | if [ -e "/proc/$proc" ]; then 20 | pid=$proc 21 | lsof -p $pid "$@" 22 | else 23 | if pgrep "$proc" >/dev/null; then 24 | pgrep_args= 25 | else 26 | echo "pgrep \"$proc\" didn't find process; trying pgrep -f ..." 27 | pgrep_args=-f 28 | fi 29 | 30 | pgrep $pgrep_args "$proc" | while read pid; do 31 | # Ugh. This is the only way to get the pid of the subshell. 32 | # $$ returns the parent pid. 33 | sub_pid=`sh -c 'echo $PPID'` 34 | if [ "$pid" == $$ ]; then 35 | : #echo " skipping top lsofp process" 36 | elif [ "$pid" == $sub_pid ]; then 37 | : #echo " skipping lsofp subshell" 38 | else 39 | lsof -p $pid "$@" 40 | fi 41 | done 42 | fi 43 | -------------------------------------------------------------------------------- /bin/lswap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # find-out-what-is-using-your-swap.sh 4 | # -- Get current swap usage for all running processes 5 | # -- 6 | # -- rev.0.3, 2012-09-03, Jan Smid - alignment and intendation, sorting 7 | # -- rev.0.2, 2012-08-09, Mikko Rantalainen - pipe the output to "sort -nk3" to get sorted output 8 | # -- rev.0.1, 2011-05-27, Erik Ljungstrom - initial version 9 | 10 | 11 | SCRIPT_NAME=`basename $0` 12 | SORT="kb"; # {pid|kB|name} as first parameter, [default: kb] 13 | [ "$1" != "" ] && { SORT="$1"; } 14 | 15 | [ ! -x `which mktemp` ] && { echo "ERROR: mktemp is not available!"; exit; } 16 | MKTEMP=`which mktemp` 17 | TMP=`${MKTEMP} -d` 18 | [ ! -d "${TMP}" ] && { echo "ERROR: unable to create temp dir!"; exit; } 19 | 20 | >${TMP}/${SCRIPT_NAME}.pid 21 | >${TMP}/${SCRIPT_NAME}.kb 22 | >${TMP}/${SCRIPT_NAME}.name 23 | 24 | SUM=0 25 | OVERALL=0 26 | echo "${OVERALL}" > ${TMP}/${SCRIPT_NAME}.overall 27 | 28 | for DIR in `find /proc/ -maxdepth 1 -type d -regex "^/proc/[0-9]+"` 29 | do 30 | PID=`echo $DIR | cut -d / -f 3` 31 | PROGNAME=`ps -p $PID -o comm --no-headers` 32 | 33 | for SWAP in `grep Swap $DIR/smaps 2>/dev/null| awk '{ print $2 }'` 34 | do 35 | let SUM=$SUM+$SWAP 36 | done 37 | 38 | if (( $SUM > 0 )) 39 | then 40 | echo -n "." 41 | echo -e "${PID}\t${SUM}\t${PROGNAME}" >> ${TMP}/${SCRIPT_NAME}.pid 42 | echo -e "${SUM}\t${PID}\t${PROGNAME}" >> ${TMP}/${SCRIPT_NAME}.kb 43 | echo -e "${PROGNAME}\t${SUM}\t${PID}" >> ${TMP}/${SCRIPT_NAME}.name 44 | fi 45 | let OVERALL=$OVERALL+$SUM 46 | SUM=0 47 | done 48 | echo "${OVERALL}" > ${TMP}/${SCRIPT_NAME}.overall 49 | echo 50 | echo "Overall swap used: ${OVERALL} kB" 51 | echo "========================================" 52 | case "${SORT}" in 53 | name ) 54 | echo -e "name\tkB\tpid" 55 | echo "========================================" 56 | cat ${TMP}/${SCRIPT_NAME}.name|sort -r 57 | ;; 58 | 59 | kb ) 60 | echo -e "kB\tpid\tname" 61 | echo "========================================" 62 | cat ${TMP}/${SCRIPT_NAME}.kb|sort -rh 63 | ;; 64 | 65 | pid | * ) 66 | echo -e "pid\tkB\tname" 67 | echo "========================================" 68 | cat ${TMP}/${SCRIPT_NAME}.pid|sort -rh 69 | ;; 70 | esac 71 | rm -fR "${TMP}/" 72 | 73 | -------------------------------------------------------------------------------- /bin/mnp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Make non-public 4 | 5 | if [ -z "$1" ]; then 6 | echo "Usage: mnp <files/dirs> ..." 7 | exit 1 8 | fi 9 | 10 | exec chmod go-rwx "$@" 11 | -------------------------------------------------------------------------------- /bin/mnt-image: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ "$OSTYPE" != linux* ]]; then 6 | echo "Not on a Linux box; aborting." 7 | exit 1 8 | fi 9 | 10 | if [[ `id -u` != 0 ]]; then 11 | echo "Not root; aborting." 12 | exit 1 13 | fi 14 | 15 | if [[ $# != 1 && $# != 2 ]]; then 16 | echo "Usage: $0 <floppy image> [ <mount point> ]" 17 | exit 1 18 | fi 19 | 20 | MNTROOT=/mnt/initrd 21 | mkdir -p $MNTROOT 22 | if ! [ -d $MNTROOT ]; then 23 | echo "Couldn't mkdir -p $MNTROOT" >&2 24 | exit 1 25 | fi 26 | 27 | img=$1 28 | imgbase=${1##*/} 29 | mnt=${2:-$MNTROOT/$imgbase} 30 | absmnt="`abs $mnt`" 31 | if mount | egrep -q "$absmnt"; then 32 | echo "Something already mounted on $absmnt! Aborting." 33 | exit 1 34 | fi 35 | 36 | [[ -d $mnt ]] || mkdir -p $mnt 37 | fs="`file $img`" 38 | case "$fs" in 39 | *FAT*) 40 | fstype=msdos ;; 41 | *ext2*) 42 | fstype=ext2 ;; 43 | *) 44 | echo -e "Image $img had unknown filesystem!\n$fs" 45 | exit 1 ;; 46 | esac 47 | 48 | echo "$img image type: $fstype" 49 | 50 | if mount -o loop -t $fstype $img $mnt; then 51 | echo Mounted $img on $mnt 52 | else 53 | echo -n "Retrying read-only ... " 54 | if ! mount -o loop,ro -t $fstype $img $mnt; then 55 | echo failed. 56 | else 57 | echo ok. 58 | fi 59 | fi 60 | -------------------------------------------------------------------------------- /bin/mnt-initrd: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ "$OSTYPE" != linux* ]]; then 6 | echo "Not on a Linux box; aborting." >&2 7 | exit 1 8 | fi 9 | 10 | if [[ `id -u` != 0 ]]; then 11 | echo "Not root; aborting." >&2 12 | exit 1 13 | fi 14 | 15 | if [[ $# != 1 ]]; then 16 | echo "Usage: $0 <initrd image>" 17 | echo " $0 <floppy image>" 18 | exit 1 19 | fi 20 | 21 | if ! [[ -f $1 ]]; then 22 | echo "$1 isn't a valid file; aborting." >&2 23 | exit 1 24 | fi 25 | 26 | case "`file $1`" in 27 | *SYSLINUX*) 28 | echo "$1 is a floppy image" # e.g. bootnet.img 29 | floppy=$1 30 | floppy_base=${1##*/} 31 | mnt-image $floppy 32 | img=mnt:$floppy_base/initrd.img 33 | imgbase=initrd.img 34 | ;; 35 | *) 36 | img=$1 37 | imgbase=${img##*/} 38 | ;; 39 | esac 40 | 41 | tmpimg=/tmp/$imgbase 42 | cp $img $tmpimg.gz 43 | gunzip $tmpimg.gz 44 | 45 | case "`file $tmpimg`" in 46 | *cpio*) 47 | echo "$tmpimg is a cpio archive" 48 | mv $tmpimg $tmpimg.cpio 49 | mkdir $tmpimg 50 | cd $tmpimg 51 | cpio -idv < $tmpimg.cpio 52 | rm $tmpimg.cpio 53 | echo "$img unpacked into $tmpimg" 54 | exit 0 55 | ;; 56 | esac 57 | 58 | mnt-image $tmpimg 59 | -------------------------------------------------------------------------------- /bin/mnt-isos: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mnt_iso () { 4 | iso="$1" 5 | if ! [ -r "$iso" ]; then 6 | echo "Can't read $iso" >&2 7 | exit 1 8 | fi 9 | 10 | name="`basename $iso`" 11 | name="${name%.iso}" 12 | mnt="/mnt/isos/$name" 13 | if ! mkdir -p "$mnt"; then 14 | echo "Couldn't mkdir $mnt" >&2 15 | exit 1 16 | fi 17 | mount -o loop "$iso" "$mnt" 18 | } 19 | 20 | if [ "$USER" != root ]; then 21 | echo "Must be root" >&2 22 | exit 1 23 | fi 24 | 25 | for iso in "$@"; do 26 | mnt_iso "$iso" 27 | done 28 | -------------------------------------------------------------------------------- /bin/mnx: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Make Not eXecutable 4 | exec chmod -x "$@" 5 | -------------------------------------------------------------------------------- /bin/mp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Make Public 4 | 5 | if [ -z "$2" ]; then 6 | echo "Usage: mp <group> <files/dirs> ..." 7 | exit 1 8 | fi 9 | 10 | chgrp "$@" 11 | shift 12 | exec chmod go+rX "$@" 13 | -------------------------------------------------------------------------------- /bin/multi-syphon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Wrapper around syphon -i 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Date::Manip qw(ParseDate UnixDate DateCalc Date_Cmp); 9 | use Getopt::Long; 10 | 11 | Getopt::Long::Configure('bundling'); 12 | 13 | my %opts = ( verbosity => 1 ); 14 | GetOptions( 15 | \%opts, 16 | 'help|h', 17 | 'dry-run|d', 18 | ) or usage(); 19 | 20 | sub usage { 21 | warn @_, "\n" if @_; 22 | 23 | (my $ME = $0) =~ s,.*/,,; 24 | 25 | die <<EOUSAGE; 26 | Usage: $ME IN-FILE FORMAT-TYPE FIRST-PERIOD LAST-PERIOD PERIOD-DURATION 27 | Options: 28 | -h, --help Show this help 29 | -d, --dry-run 30 | 31 | e.g. $ME error.log apache2 'July 2010' 'Oct 2010' '1 month' 32 | 33 | First period should be the first period contained in the input file, 34 | otherwise the first bucket file generated will contain entries from 35 | multiple periods. TODO: auto-detect this. 36 | 37 | Last period is included, so a file for it will be created. 38 | EOUSAGE 39 | } 40 | 41 | usage() if @ARGV != 5 or $opts{help}; 42 | 43 | my %formats = ( 44 | # Typical Apache error log 45 | # [Wed Jul 01 13:18:53 2009] .... 46 | 'apache1' => '^\[%a %b %d %T %Y\]', 47 | 48 | # Typical Apache access log 49 | # 178.154.163.29 - - [16/Apr/2011:13:40:44 +0000] "GET ... 50 | 'apache2' => '^\d[\d.]+ - - \[%d/%b/%Y:%T ', 51 | 52 | # /var/www/wordpress/wp-content/debug.log 53 | # [02-Feb-2011 09:53:13] ... 54 | 'wp-debug' => '^\[%d-%b-%Y %T\] ', 55 | 56 | # date output 57 | # Fri Apr 1 00:59:01 UTC 2011 58 | 'date' => '^%a %b %e %T ... %Y', 59 | ); 60 | 61 | my ($in_file, $format_type, $first_period_start, $end, $duration) = @ARGV; 62 | 63 | my $format = $formats{$format_type}; 64 | $format or die "Unrecognised format '$format_type'\n"; 65 | my $pattern_template = $format; 66 | $pattern_template =~ s/%T/[ \\d]\\d:\\d\\d:\\d\\d/g; 67 | if ($duration =~ /month/) { 68 | $pattern_template =~ s/%d/\\d\\d/g; 69 | $pattern_template =~ s/%e/[ \\d]\\d/g; 70 | } 71 | $pattern_template =~ s/%a/\\w{3}/g; 72 | 73 | my $start_date = ParseDate($first_period_start); 74 | my $end_date = ParseDate($end); 75 | while (1) { 76 | # print " " . UnixDate($start_date, "%c") . "\n"; 77 | # print " " . UnixDate($end_date, "%c") . "\n"; 78 | last if Date_Cmp($start_date, $end_date) > 0; 79 | syphon_period($in_file, $format, $start_date, $duration); 80 | $start_date = DateCalc($start_date, "+$duration"); 81 | } 82 | 83 | sub output_cmd { 84 | my @cmd = (); 85 | for my $a (@_) { 86 | my $arg = $a; # no in-place modification evilness 87 | if ($arg =~ /["' ]/) { 88 | $arg =~ s/"/\\"/g; 89 | $arg = qq!"$arg"!; 90 | } 91 | push @cmd, $arg; 92 | } 93 | print join(" ", @cmd), "\n"; 94 | } 95 | 96 | sub syphon_period { 97 | my ($in_file, $format, $period_start, $duration) = @_; 98 | 99 | my $period_end = DateCalc($period_start, "+$duration"); 100 | # print "Syphoning period from:\n"; 101 | # print " " . UnixDate($period_start, "%c") . "\n"; 102 | # print "to:\n"; 103 | # print " " . UnixDate($period_end, "%c") . "\n"; 104 | 105 | my $pattern = UnixDate($period_end, $pattern_template); 106 | 107 | my $suffix = $duration =~ /month/ ? "-%Y-%m" : "-%Y-%m-%d"; 108 | 109 | my $out_file = $in_file . UnixDate($period_start, $suffix); 110 | my @cmd = ( 111 | 'syphon', '-i', 112 | $pattern, 113 | $in_file, 114 | $out_file, 115 | ); 116 | output_cmd(@cmd); 117 | unless ($opts{'dry-run'}) { 118 | system(@cmd); 119 | die "Command failed\n" if $? > 0; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /bin/mv-merge: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Moves the entire contents of one directory to another, even if some 4 | # subdirectories are common to both source and destination directories. 5 | # 6 | # Uses rsync and rm-src-dups. 7 | # 8 | # Adam Spiers <me@adamspiers.org> 9 | # 10 | 11 | set -e 12 | me=`basename $0` 13 | 14 | usage () { 15 | # Call as: usage [EXITCODE] [USAGE MESSAGE] 16 | exit_code=1 17 | if [[ "$1" == [0-9] ]]; then 18 | exit_code="$1" 19 | shift 20 | fi 21 | if [ -n "$1" ]; then 22 | echo "$*" >&2 23 | echo 24 | fi 25 | 26 | cat <<EOF >&2 27 | Usage: $me [OPTIONS] SRC [SRC ...] DESTDIR 28 | 29 | SRCs should be relative to the current directory. 30 | DESTDIR can be relative or absolute. 31 | 32 | Options (must be in order specified above!) 33 | -f Force overwrites of existing files in dest tree 34 | (does not overwrite by default) 35 | -u Update existing files in dest tree only if source is newer 36 | -n, --dry-run Don't actually do anything. 37 | EOF 38 | exit "$exit_code" 39 | } 40 | 41 | parse_opts () { 42 | overwrite="--ignore-existing" 43 | 44 | while [ $# != 0 ]; do 45 | case "$1" in 46 | -h|--help) 47 | usage 0 48 | ;; 49 | -n|--dry-run) 50 | dry_run=--dry-run 51 | shift 52 | ;; 53 | -f) 54 | overwrite="" 55 | shift 56 | ;; 57 | -u) 58 | # takes precedence over -f 59 | overwrite="--update" 60 | shift 61 | ;; 62 | -*) 63 | usage "Unrecognized option $1" 64 | ;; 65 | *) 66 | break 67 | ;; 68 | esac 69 | done 70 | 71 | if [ $# -lt 2 ]; then 72 | usage "Need at least two parameters" 73 | fi 74 | 75 | srcs=( "${@:1:$(($#-1))}" ) 76 | dst="${@: -1:1}" 77 | 78 | if ! [ -d "$dst" ]; then 79 | usage "$dst is not a directory" 80 | fi 81 | } 82 | 83 | if ! which rsync 2>&1 >/dev/null; then 84 | echo "rsync must be on \$PATH for $me to work." >&2 85 | exit 1 86 | fi 87 | 88 | parse_opts "$@" 89 | 90 | abs_cwd=`pwd` 91 | for src in "${srcs[@]}"; do 92 | echo rsync -Rav --link-dest=\""$abs_cwd"\" $dry_run $overwrite \""$src"\" \""$dst"\" 93 | rsync -Rav --link-dest="$abs_cwd" $dry_run $overwrite "$src" "$dst" 94 | 95 | echo 96 | echo rm-src-dups -vv $dry_run -s \""$src"\" . \""$dst"\" 97 | [ -d "$dst/$src" ] && rm-src-dups -vv $dry_run -s "$src" . "$dst" 98 | done 99 | -------------------------------------------------------------------------------- /bin/mvi: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec mv -i "$@" 4 | -------------------------------------------------------------------------------- /bin/mx: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Make eXecutable 4 | exec chmod +x "$@" 5 | -------------------------------------------------------------------------------- /bin/newer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Date::Manip qw{Delta_Format DateCalc UnixDate}; 7 | use File::Basename; 8 | use File::stat; 9 | use Getopt::Long; 10 | 11 | my %opts; 12 | GetOptions(\%opts, 'atime|a', 'ctime|c', 'mtime|m', 'help|h'); 13 | 14 | my $me = basename $0; 15 | 16 | sub usage { 17 | warn @_, "\n" if @_; 18 | die <<EOF; 19 | Usage: $me [OPTIONS] FILE AGE 20 | Options: 21 | -a, --atime 22 | -c, --ctime 23 | -m, --mtime (default) 24 | 25 | Exit code is zero iff FILE is newer than AGE. 26 | 27 | AGE is passed to Date::Manip::ParseDateDelta() to parse; 28 | the following are all valid examples of the same time: 29 | 30 | 25hr 2min 58s 31 | 25 hours 3mn -2second 32 | 25 hr 3 minutes -2 33 | 25 hour + 3 min -2 s 34 | 1 day 1 hour 178 s 35 | 90178s 36 | EOF 37 | } 38 | 39 | usage() if $opts{help}; 40 | usage() unless @ARGV >= 2; 41 | 42 | my ($file, @age) = @ARGV; 43 | my $age_str = "@age"; 44 | my $st = stat($file); 45 | $st or die "stat($file) failed: $!\n"; 46 | my $file_age = $opts{atime} ? $st->atime 47 | : $opts{ctime} ? $st->ctime 48 | : $st->mtime; 49 | 50 | my $err; 51 | # Figure out age threshold in seconds since UNIX epoch. 52 | my $threshold = DateCalc("now", "-$age_str", \$err); 53 | die "DateCalc error: $err\n" if $err; 54 | 55 | my $threshold2 = UnixDate($threshold, "%s"); 56 | #printf "File: %12s\nThreshold:%12s\n", $file_age, $threshold2; 57 | exit(($file_age > $threshold2) ? 0 : 1); 58 | -------------------------------------------------------------------------------- /bin/nm-current-connection: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | type="${1:-wifi}" 4 | 5 | nmcli -f type,name connection show --active | \ 6 | grep "$type" | \ 7 | sed "s/^$type \\+//" 8 | -------------------------------------------------------------------------------- /bin/nm-current-connections: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nmcli connection show --active 4 | -------------------------------------------------------------------------------- /bin/nmw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nmcli d wifi "$@" 4 | -------------------------------------------------------------------------------- /bin/nmwc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nmw connect "$@" 4 | -------------------------------------------------------------------------------- /bin/nth: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | me=`basename $0` 4 | 5 | usage () { 6 | cat <<EOF >&2 7 | Usage: $me NTH FILE [ FILE ... ] 8 | EOF 9 | exit 1 10 | } 11 | 12 | if [ "$1" == -h ] || [ "$1" == --help ] || [ -z "$1" ]; then 13 | usage 14 | fi 15 | 16 | nth="$1" 17 | shift 18 | 19 | awk "{ if (FNR == $nth) { print; nextfile; } }" "$@" 20 | -------------------------------------------------------------------------------- /bin/ntrace: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if which strace 2>&1 >/dev/null; then 3 | strace -e trace=network "$@" 4 | else 5 | echo "strace not found" >&2 6 | exit 1 7 | fi 8 | -------------------------------------------------------------------------------- /bin/open: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | url-handler "$@" 4 | -------------------------------------------------------------------------------- /bin/ord: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | foreach my $ord (split //, shift) { 7 | printf "%s: dec %d, oct %03o, hex 0x%02x\n", $ord, (ord $ord) x 3; 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /bin/ox: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec objdump -x "$@" 4 | -------------------------------------------------------------------------------- /bin/pdf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # See ~/org/notes/PDFviewers.org for justification on decision order 4 | viewers='kpdf evince okular acroread xpdf' 5 | 6 | found= 7 | for file in "$@"; do 8 | if [ -r "$file" ]; then 9 | found=y 10 | else 11 | echo "$file doesn't exist or unreadable!" >&2 12 | fi 13 | done 14 | 15 | if [ -z "$found" ]; then 16 | echo "No valid file found; aborting!" >&2 17 | exit 1 18 | fi 19 | 20 | # acroread -help gets truncated before echoing 'openInNewWindow' 21 | # when STDOUT is not a tty?! 22 | 23 | # if acroread -helpall | grep -q openInNewWindow; then 24 | acro_opts=-openInNewWindow 25 | # else 26 | # acro_opts= 27 | # fi 28 | 29 | exe= 30 | for exe_check in $viewers; do 31 | if which $exe_check >/dev/null 2>&1; then 32 | exe=$exe_check 33 | # echo "Will use $exe ..." 34 | break 35 | else 36 | : 37 | # echo "$exe_check not found" 38 | fi 39 | done 40 | 41 | if [ -z "$exe" ]; then 42 | echo "No PDF viewer found; aborting." >&2 43 | exit 1 44 | fi 45 | 46 | if [ "$exe" = "acroread" ]; then 47 | opts="$acro_opts" 48 | fi 49 | 50 | "$exe" $opts "$@" 51 | -------------------------------------------------------------------------------- /bin/penv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This was actually a winner in one of the obfuscated Perl 4 | # competitions, way back in the day. 5 | 6 | perl -0l12pe1 /proc/$1/environ 7 | -------------------------------------------------------------------------------- /bin/phup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pkill -HUP "$@" 4 | -------------------------------------------------------------------------------- /bin/pinggw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gateway=$( gw-IP ) 4 | 5 | if [ -z "$gateway" ]; then 6 | echo "Could not find default route via route -n:" >&2 7 | route -n >&2 8 | exit 1 9 | fi 10 | 11 | ping "$@" "$gateway" 12 | -------------------------------------------------------------------------------- /bin/pingns: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -n "$1" ]; then 4 | num="$1" 5 | shift 6 | else 7 | num=1 8 | fi 9 | 10 | ns=$( perl -0777ne 'my @ns = /^ *nameserver +([0-9.]+)/mg; 11 | print $ns['$num' - 1] || ""' \ 12 | /etc/resolv.conf ) 13 | 14 | if [ -z "$ns" ]; then 15 | echo "Could not find nameserver $num in /etc/resolv.conf" >&2 16 | exit 1 17 | fi 18 | 19 | ping "$@" "$ns" 20 | -------------------------------------------------------------------------------- /bin/pingwan: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gateway=$( find-wan-gateway ) 4 | 5 | if [ -z "$gateway" ]; then 6 | echo "Could not find default route via route -n:" >&2 7 | route -n >&2 8 | exit 1 9 | fi 10 | 11 | ping "$@" "$gateway" 12 | -------------------------------------------------------------------------------- /bin/protect: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | handler () { 4 | echo got a signal 5 | } 6 | 7 | trap handler EXIT HUP INT QUIT TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH PWR SYS 8 | 9 | while true; do 10 | echo $$ still here 11 | sleep 1 12 | done 13 | -------------------------------------------------------------------------------- /bin/pst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | linux_detect_ascii () { 4 | ascii= 5 | pstree --help 2>&1 | grep -q -- '-A .*ASCII' && ascii=-A 6 | } 7 | 8 | linux_pstree () { 9 | LANG=C pstree $ascii -p "$@" 10 | } 11 | 12 | linux_iterate () { 13 | opts=( ) 14 | while [ -n "$1" ]; do 15 | case "$1" in 16 | -*) 17 | opts=( "${opts[@]}" "$1" ) 18 | shift 19 | ;; 20 | *) 21 | break 22 | ;; 23 | esac 24 | done 25 | 26 | if [ $# = 0 ]; then 27 | linux_pstree "${opts[@]}" 28 | elif [ -d "/proc/$1" ]; then 29 | linux_pstree "${opts[@]}" "$@" 30 | else 31 | for proc in "$@"; do 32 | echo "Searching for processes containing '$proc' ..." 33 | for pid in `pgrep -f "$proc"`; do 34 | #echo "Tree for pid $pid:" 35 | linux_pstree "${opts[@]}" "$pid" 36 | done 37 | done 38 | fi 39 | } 40 | 41 | case "$OSTYPE" in 42 | solaris*) 43 | exec ptree "$@" | less -rS 44 | ;; 45 | *) 46 | if ! which pstree 2>&1 >/dev/null; then 47 | echo "pstree not found." 48 | exit 1 49 | fi 50 | 51 | linux_detect_ascii 52 | 53 | linux_iterate "$@" | less -rSFX 54 | ;; 55 | esac 56 | 57 | -------------------------------------------------------------------------------- /bin/pstt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec pst -hal "$@" 4 | -------------------------------------------------------------------------------- /bin/quietrun: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # quietrun -- run a command and only allow output if the exit code 4 | # didn't reflect success. 5 | # Copyright (c) 1999 Adam Spiers <adam@spiers.net> 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. 19 | 20 | # See also chronic from moreutils which does the same thing without 21 | # temporary files: 22 | # http://git.kitenet.net/?p=moreutils.git;a=blob;f=chronic;hb=HEAD 23 | 24 | tmpdir=/tmp/quietrun.$$ 25 | # Half-heartedly guard against symlink attacks/accidents. There's 26 | # still a race. Hmm. Does anyone actually care? 27 | [ -e $tmpdir ] && rm -rf $tmpdir 28 | if [ -e $tmpdir ]; then 29 | echo "Couldn't remove $tmpdir; aborting." 30 | exit 1 31 | fi 32 | if ! mkdir $tmpdir; then 33 | echo "Couldn't create $tmpdir; aborting." 34 | exit 1 35 | fi 36 | 37 | if [ "$1" = '-h' ] || [ "$1" = '--help' ]; then 38 | cat <<'EOF' 39 | Usage: quietrun [ -m | --merge ] <command> [ <args> ... ] 40 | 41 | If the merge option is specified, stdout and stderr are merged into 42 | stdout, but the output order is preserved. Otherwise they kept 43 | separate, but output from stderr only appears after output from stdout. 44 | 45 | The exit code from the command is preserved. 46 | EOF 47 | exit 0 48 | fi 49 | 50 | if [ "$1" = '-m' ] || [ "$1" = '--merge' ]; then 51 | shift 52 | merge=yes 53 | fi 54 | 55 | if [ $# -eq 0 ]; then 56 | echo "quietrun: no command supplied" 57 | exit 1 58 | fi 59 | 60 | if [ "$merge" = 'yes' ]; then 61 | "$@" 2>&1 >$tmpdir/both 62 | exit_code=$? 63 | if [ $exit_code != 0 ]; then 64 | [ -e "$tmpdir/both" ] && cat $tmpdir/both 65 | fi 66 | else 67 | "$@" >$tmpdir/stdout 2>$tmpdir/stderr 68 | exit_code=$? 69 | if [ $exit_code != 0 ]; then 70 | [ -e "$tmpdir/stdout" ] && cat $tmpdir/stdout 71 | [ -e "$tmpdir/stderr" ] && cat $tmpdir/stderr 1>&2 2>/dev/null 72 | fi 73 | fi 74 | 75 | rm -rf $tmpdir 76 | 77 | exit $exit_code 78 | -------------------------------------------------------------------------------- /bin/ra: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | here=`dirname $0` 4 | here=${here:-.} 5 | 6 | user="${USERNAME:-${USER:-dontmatch}}" 7 | [ "$user" = root ] && user=dontmatch 8 | exec rj "$@" | egrep -vf $here/ra.pats | grep -vE "^$user|$0\$" 9 | -------------------------------------------------------------------------------- /bin/ra.pats: -------------------------------------------------------------------------------- 1 | ^nobody 2 | ^bin 3 | ^named 4 | ^lp 5 | ^mysql 6 | ^postfix 7 | ^xfs 8 | ^mail 9 | ^httpd 10 | ^apache 11 | init$ 12 | syslogd 13 | klogd 14 | login 15 | gpm -t 16 | crond 17 | /cron$ 18 | ypbind 19 | ypserv 20 | sendmail 21 | getty 22 | sshd 23 | kshd( -e)?( -5)? 24 | x?inetd 25 | rpcbind 26 | statd$ 27 | lockd$ 28 | mountd$ 29 | powerd$ 30 | utmpd$ 31 | mutt 32 | pine 33 | -?(ba|k|t?c|z)?sh( -o (vi|emacs)| \((ba|k|t?c|z)?sh\))?$ 34 | portmap$ 35 | rpc.statd$ 36 | ntpd( -U ntp)?$ 37 | /atd$ 38 | sched 39 | init[ -]?\[[0-9]+\] *$ 40 | \[[[:alnum:]_]+\]$ 41 | -------------------------------------------------------------------------------- /bin/ran: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -wl 2 | # 3 | # Advanced replacement for seq(1) 4 | # 5 | # Adam Spiers <ran@adamspiers.org> 6 | # 7 | # $Id$ 8 | 9 | use Getopt::Long; 10 | my %opts; 11 | GetOptions( 12 | \%opts, 13 | 'help', 14 | 'delimiter=s', 'format=s', 'lines', 'space-pad|p', 'zero-pad|z', 15 | ) or usage(); 16 | usage() if @ARGV == 0 or $opts{help}; 17 | my $delimiter = delimiter(); 18 | my @items = eval "@ARGV"; 19 | my $format = get_format(\@items); 20 | my @formatted_items = map { sprintf $format, $_ } @items; 21 | print join qqexpand($delimiter), @formatted_items; 22 | 23 | sub usage { 24 | warn @_, "\n" if @_; 25 | 26 | die <<EOUSAGE; 27 | Usage: ran [options] <Perl list> 28 | Options: 29 | -d, --delimiter=STR Set output delimiter 30 | -l, --lines Set output delimiter to \\n 31 | -f, --format=STR Use printf format string 32 | -p, --space-pad Equalize width by padding with spaces 33 | -z, --zero-pad Equalize width by padding with leading zeroes 34 | EOUSAGE 35 | } 36 | 37 | sub qqexpand { 38 | my ($delimiter) = @_; 39 | $delimiter =~ s!\\([efnrt]|x\d\d?|0\d{2,3})!qq["$&"]!gee; 40 | return $delimiter; 41 | } 42 | 43 | sub get_format { 44 | my ($items) = @_; 45 | 46 | my @foo = map { defined $opts{$_} ? 1 : 0 } qw(format space-pad zero-pad); 47 | usage("You must only select one output format.\n") 48 | if $foo[0] + $foo[1] + $foo[2] > 1; 49 | 50 | return '%0' . max_width($items) . 'd' if $opts{'zero-pad'}; 51 | return '%' . max_width($items) . 's' if $opts{'space-pad'}; 52 | return $opts{format} if $opts{'format'}; 53 | return '%s'; 54 | } 55 | 56 | sub max_width { 57 | my ($items) = @_; 58 | my $max_width = 0; 59 | for (@$items) { 60 | $max_width = length if length > $max_width; 61 | } 62 | return $max_width; 63 | } 64 | 65 | sub delimiter { 66 | usage("You cannot specify both --delimiter and --lines.\n") 67 | if $opts{delimiter} && $opts{lines}; 68 | 69 | return "\n" if $opts{lines}; 70 | return $opts{delimiter} || ' '; 71 | } 72 | -------------------------------------------------------------------------------- /bin/rc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rclone "$@" 4 | -------------------------------------------------------------------------------- /bin/rcg: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rclone rcd --rc-web-gui "$@" 4 | -------------------------------------------------------------------------------- /bin/rcslocks: -------------------------------------------------------------------------------- 1 | #!/opt/perl-5.6.1/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Long; 7 | use Mail::Send; 8 | 9 | use lib '/home/lonlxadm/lib/perl5'; 10 | use Rcs; 11 | 12 | my %opts; 13 | die <<EOF unless GetOptions(\%opts, 'mail') and @ARGV; 14 | Usage: $0 [--mail] <file> [<file> ...] 15 | Options: 16 | --mail Send reminder e-mail to lock owners 17 | EOF 18 | 19 | my $short = (@ARGV == 1); 20 | 21 | my %lockers; 22 | my %seen; 23 | foreach my $file (@ARGV) { 24 | unless (-e $file) { 25 | warn "File '$file' does not exist; skipping.\n"; 26 | next; 27 | } 28 | unless (-f $file) { 29 | warn "'$file' is not a file; skipping.\n"; 30 | next; 31 | } 32 | my $rcsfile = find_rcs($file); 33 | next unless $rcsfile; 34 | next if $seen{$rcsfile}++; 35 | my $rcs = Rcs->new($rcsfile); 36 | my $locker = $rcs->lock; 37 | if ($locker) { 38 | print $short ? "$locker\n" : "$file locked by $locker\n"; 39 | push @{ $lockers{$locker} }, $file; 40 | } 41 | } 42 | 43 | if ($opts{mail}) { 44 | while (my ($locker, $files) = each %lockers) { 45 | my $msg = new Mail::Send Subject => "automated warning: you have RCS files locked"; 46 | my $address = "$locker\@lehman.com"; 47 | $msg->to($address); 48 | my $fh = $msg->open; 49 | my $file = @$files == 1 ? 'file' : 'files'; 50 | print $fh <<EOMSG; 51 | This is an automated email to remind you that you have the following 52 | $file locked under RCS: 53 | 54 | EOMSG 55 | print $fh " $_\n" foreach @$files; 56 | if (@$files == 1) { 57 | print $fh <<EOMSG; 58 | 59 | If you have finished editing it, please check it back in. 60 | Thanks. 61 | EOMSG 62 | } 63 | else { 64 | print $fh <<EOMSG; 65 | 66 | If you have finished editing any of them, please check them back in. 67 | Thanks. 68 | EOMSG 69 | } 70 | 71 | print $fh <<EOMSG; 72 | 73 | To see changes not yet checked in: 74 | 75 | rcsdiff $file 76 | 77 | To check in changes, do: 78 | 79 | ci -u $file # stands for Check In and leave working file Unlocked 80 | 81 | To revert to the previous version, do: 82 | 83 | co -u $file # stands for Check Out and leave working file Unlocked 84 | 85 | If you don't like having to remember all this, get used to editing 86 | RCS-controlled files with the 'viz' utility. 87 | EOMSG 88 | 89 | $fh->close; 90 | print "Sent mail to $address\n"; 91 | } 92 | } 93 | 94 | sub find_rcs { 95 | my ($file) = @_; 96 | return $file if $file =~ /,v$/; 97 | (my $rcsfile = $file) =~ s!([^/]+)$!RCS/$1,v!; 98 | return $rcsfile if -e $rcsfile; 99 | $rcsfile = "$file,v"; 100 | return $rcsfile if -e $rcsfile; 101 | warn "Couldn't find RCS file for $file\n"; 102 | return undef; 103 | } 104 | -------------------------------------------------------------------------------- /bin/resolver-domain: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | awk '/^ *search/ { print $2; exit 0 }' /etc/resolv.conf | sed 's/\.$//' 4 | -------------------------------------------------------------------------------- /bin/rj: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | case "$0" in 4 | *rjt) threads='-L' ;; 5 | *) threads='' ;; 6 | esac 7 | 8 | # beginnings of a cleaner way then the grep -v grep nonsense 9 | # ps $opts | awk "(NR == 1) || /$1/" 10 | 11 | case "$OSTYPE" in 12 | solaris*) exec /usr/bin/ps -ef $threads | 13 | egrep -v "grep.+USER|$0|ps -ef\$" | 14 | egrep --color=always "($*|^ *UID)" 15 | ;; 16 | 17 | # FreeBSD and Linux 18 | *) exec ps auxwwww $threads | 19 | egrep -v "grep.+USER|$0|ps auxwwww\$" | 20 | egrep --color=always "($*|^USER)" 21 | ;; 22 | esac 23 | -------------------------------------------------------------------------------- /bin/rjd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Search for uninterruptible processes 4 | rj " D[N+ ]" 5 | -------------------------------------------------------------------------------- /bin/rjr: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ps auxwwwwr "$@" 4 | -------------------------------------------------------------------------------- /bin/rm-src-dups: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use File::Find; 7 | use File::Spec; 8 | use FindBin qw($RealBin); 9 | use Getopt::Long; 10 | use List::Util; 11 | 12 | sub usage { 13 | die <<EOUSAGE; 14 | Usage: $RealBin [options] SRC DST 15 | 16 | Removes files from SRC which were already identically in DST. 17 | 18 | Options: 19 | -n, --dry-run Just show what would have been removed 20 | -k, --keep-dirs Don't prune empty directories 21 | -s SUBPATH Only work in SUBPATH of SRC and DST 22 | -v, --verbose 23 | -h, --help 24 | EOUSAGE 25 | } 26 | 27 | my %opts = (); 28 | Getopt::Long::Configure('bundling'); 29 | GetOptions( 30 | \%opts, 31 | 'dry-run|n', 'keep-dirs|k', 'subpath|s=s', 'verbose|v', 'help|h' 32 | ) or usage(); 33 | usage() if $opts{help} || @ARGV != 2; 34 | 35 | my ($src, $dst) = @ARGV; 36 | 37 | if ($opts{subpath}) { 38 | $src = File::Spec->join($src, $opts{subpath}); 39 | $dst = File::Spec->join($dst, $opts{subpath}); 40 | } 41 | 42 | my %doomed = (); 43 | 44 | rm_src_dups($src, $dst); 45 | 46 | unless ($opts{'keep-dirs'}) { 47 | #chdir "/" or die "chdir(/) failed: $!\n"; 48 | finddepth({ wanted => \&prune_empty_dirs, no_chdir => 1}, $src); 49 | } 50 | 51 | exit 0; 52 | 53 | sub rm_src_dups { 54 | my ($src, $dst) = @_; 55 | -d $src or die "$src isn't a directory\n"; 56 | -d $dst or die "$dst isn't a directory\n"; 57 | 58 | my $pid = open(DIFF, "-|"); 59 | defined $pid or die "fork failed: $!\n"; 60 | if (! $pid) { 61 | # in child 62 | my @args = ( "diff", '-r', '--report-identical-files', '--brief', $src, $dst ); 63 | exec @args or die "exec(@args) failed: $!\n"; 64 | } 65 | 66 | while (<DIFF>) { 67 | chomp; 68 | 69 | if (/^Files (.+) and (\Q$dst\E.+) are identical$/) { 70 | do_unlink($1); 71 | next; 72 | } 73 | elsif (/^Files (.+) and (\Q$dst\E.+) differ$/) { 74 | warn "$1 and $2 differ\n" if $opts{verbose}; 75 | next; 76 | } 77 | } 78 | } 79 | 80 | sub do_unlink { 81 | my ($doomed) = @_; 82 | if ($opts{'dry-run'}) { 83 | warn qq{rm "$doomed"\n}; 84 | $doomed{$doomed}++; 85 | } 86 | else { 87 | if (unlink($doomed)) { 88 | warn qq{rm "$doomed"\n} if $opts{verbose}; 89 | } 90 | else { 91 | warn "unlink($doomed) failed: $!\n"; 92 | } 93 | } 94 | } 95 | 96 | sub prune_empty_dirs { 97 | return unless -d; 98 | 99 | if (dir_is_empty($_)) { 100 | if ($opts{'dry-run'}) { 101 | warn qq{rmdir "$_"\n}; 102 | $doomed{$_}++; 103 | } 104 | else { 105 | warn qq{rmdir "$_"\n} if $opts{verbose}; 106 | rmdir($_) or die "rmdir($_) failed: $!\n"; 107 | } 108 | } 109 | else { 110 | warn qq{Leaving non-empty dir "$_"\n} if $opts{verbose}; 111 | } 112 | } 113 | 114 | sub dir_is_empty { 115 | my ($dir) = @_; 116 | 117 | opendir(DIR, $dir) or die "opendir($dir) failed: $!\n"; 118 | my $got_one = 0; 119 | while (my $dirent = readdir(DIR)) { 120 | next if $dirent eq '.' or $dirent eq '..' or $doomed{"$dir/$dirent"}; 121 | $got_one++; 122 | last; 123 | } 124 | closedir(DIR); 125 | return $got_one ? 0 : 1; 126 | } 127 | 128 | -------------------------------------------------------------------------------- /bin/root-zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | eval spawn -noecho $argv 4 | expect { 5 | -timeout 20 6 | -re "Password for .*: " { 7 | stty -echo 8 | interact { 9 | "\r" { 10 | send "\n" 11 | return 12 | } 13 | } 14 | exp_continue 15 | } 16 | 17 | " root]#" { 18 | send "/home/aspiers/bin/zsh\n" 19 | interact 20 | } 21 | 22 | " root#" { 23 | send "/home/aspiers/bin/zsh\n" 24 | interact 25 | } 26 | 27 | # Match prompts here 28 | {\$} interact 29 | -re "\n(root@\[a-z0-9-\]+ )?# ?$" { 30 | # Solaris box :-( 31 | send "bash\rset -o emacs\r" 32 | interact 33 | } 34 | 35 | timeout interact 36 | eof 37 | } 38 | -------------------------------------------------------------------------------- /bin/rot13: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec tr A-Za-z N-ZA-Mn-za-m 3 | -------------------------------------------------------------------------------- /bin/rotate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$1" ]; then 4 | echo "Usage: $0 [ <degrees> ] <images> ... [ <degrees> <images> ... ] ..." 5 | exit 1 6 | fi 7 | 8 | angle=90 9 | 10 | for arg in "$@"; do 11 | if [ "$arg" = 90 ] || [ "$arg" = 180 ] || [ "$arg" = 270 ]; then 12 | angle="$arg" 13 | shift 14 | else 15 | file="$arg" 16 | shift 17 | newfile="${file}.$angle.$$" 18 | jpegtran -rotate $angle -copy all "$file" > "$newfile" 19 | [ -s "$newfile" ] && mv "$newfile" "$file" 20 | fi 21 | done 22 | 23 | -------------------------------------------------------------------------------- /bin/rpath: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec ox "$@" | grep -i rpath 4 | -------------------------------------------------------------------------------- /bin/safe-pipe: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This guarantees that piping data through a command which might fail 4 | # is equivalent to piping it through cat (i.e. untouched), rather than 5 | # just losing the data. E.g.: 6 | # 7 | # wget -o- http://foo.bar/baz.html | \ 8 | # safe-pipe riskily-munge-HTML | grep foo 9 | # 10 | # Its Achilles' heel is that it assumes the filter will always play nice 11 | # and return a non-zero exit code on failure, i.e. iff no output was generated. 12 | 13 | tmp=`mktemp /tmp/safe-pipe.XXXXXXXXX` 14 | cat >> $tmp 15 | 16 | # FIXME: save output of risky filter somewhere and only do cat if 17 | # non-zero exit code *and* no output was generated. Otherwise we 18 | # could get two lots of output. Though maybe that's what we want 19 | # in some circumstances? 20 | "$@" < $tmp || cat $tmp 21 | 22 | rm $tmp 23 | -------------------------------------------------------------------------------- /bin/service-commands: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me="service-commands" 4 | mode=`basename $0` 5 | 6 | if [ "$mode" = "$me" ] && [ -z "$*" ]; then 7 | here=`dirname $0` 8 | echo -n "Setting up handy service shortcuts in $here ... " 9 | cd "$here" 10 | for op in {,u}s{re,rl,st,t,sp,p,ta}; do 11 | if ! [ -e $op ]; then 12 | ln -s $me $op 13 | echo -n " $op" 14 | fi 15 | done 16 | echo 17 | exit 0 18 | fi 19 | 20 | user= 21 | case "$mode" in 22 | u*) 23 | user=--user 24 | mode="${mode#u}" 25 | ;; 26 | esac 27 | 28 | case "$mode" in 29 | sre) 30 | op=restart ;; 31 | srl) 32 | op=reload ;; 33 | st|sst) 34 | op=start ;; 35 | sp|ssp) 36 | op=stop ;; 37 | sta) 38 | op=status ;; 39 | *) 40 | echo "$0: Unrecognised mode '$mode'"; exit 1 ;; 41 | esac 42 | 43 | service="$1" 44 | if [ -n "$1" ]; then 45 | shift 46 | elif [ "$op" != status ]; then 47 | echo >&2 "Missing service name; aborting" 48 | exit 1 49 | fi 50 | 51 | if [ "`id -u`" != 0 ] && [ -z "$user" ]; then 52 | # 'ave a go son 53 | sudo=sudo 54 | else 55 | sudo= 56 | fi 57 | 58 | if which systemctl >&/dev/null; then 59 | case $op in 60 | status) 61 | # For some moronic reason, systemctl --lines=N status doesn't 62 | # work properly. I'm guessing it only shows lines since the 63 | # service was 64 | $sudo systemctl -n 0 --no-pager $user $op $service "$@" 65 | if [[ -z $user ]]; then 66 | unit_option=-u 67 | else 68 | unit_option=--user-unit 69 | fi 70 | echo 71 | $sudo journalctl -n 10 --no-pager $user $unit_option $service "$@" 72 | ;; 73 | *) 74 | exec $sudo systemctl $user $op $service "$@" 75 | ;; 76 | esac 77 | elif [ -x /sbin/service ]; then 78 | # legacy v1 79 | exec $sudo /sbin/service "$service" $op "$@" 80 | else 81 | # legacy v2 82 | exec $sudo /etc/init.d/"$service" $op "$@" 83 | fi 84 | -------------------------------------------------------------------------------- /bin/sfind: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | find "$@" -follow -type f -o -type l | source-only 4 | -------------------------------------------------------------------------------- /bin/show-colours: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # display all console colours 4 | 5 | echo -e "\e[0mno bold" 6 | for bg in `seq 40 47`; do 7 | for fg in `seq 30 37`; do 8 | code="$fg;$bg" 9 | echo -en "\e[0;${code}m $code \e[0m " 10 | done 11 | echo 12 | done 13 | 14 | echo 15 | echo -e "\e[1mbold (foreground only)" 16 | for bg in `seq 40 47`; do 17 | for fg in `seq 30 37`; do 18 | code="$fg;$bg" 19 | echo -en "\e[1;${code}m $code \e[0m " 20 | done 21 | echo 22 | done 23 | 24 | echo 25 | echo "See also tty-colours." 26 | -------------------------------------------------------------------------------- /bin/shuffle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | 5 | # For the sake of portability, we implement the shuffle ourselves 6 | # rather than depend on a CPAN module. 7 | 8 | #use List::Util 'shuffle'; 9 | #print shuffle <>; 10 | 11 | # Pinched straight from perlfaq4 12 | sub shuffle { 13 | my $deck = shift; # $deck is a reference to an array 14 | my $i = @$deck; 15 | while ($i--) { 16 | my $j = int rand ($i+1); 17 | @$deck[$i,$j] = @$deck[$j,$i]; 18 | } 19 | } 20 | 21 | my @lines = <>; 22 | shuffle(\@lines); 23 | print @lines; 24 | -------------------------------------------------------------------------------- /bin/so: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec source-only "$@" 4 | -------------------------------------------------------------------------------- /bin/sort-bash-history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | puts readlines. 4 | drop_while {|x| ! x.start_with? "#" }. # first line needs to start with "#" 5 | join. 6 | force_encoding(Encoding::ASCII_8BIT). 7 | split(/(?=^#)/). 8 | sort 9 | -------------------------------------------------------------------------------- /bin/sort-by-filename: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Sort list of newline-separated paths by filename, ignoring 4 | # path segments. Should cope with funny characters in filename 5 | # except for tabs! 6 | 7 | sed ' 8 | s/^\([^/]\+\)$/\1\t\1/; 9 | s/\(.\+\/\)\(.\+\)/\2\t\1\2/ 10 | ' | 11 | sort -n -k1 -t" " | 12 | awk -F" " '{print $2}' 13 | -------------------------------------------------------------------------------- /bin/source-only: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Source Only 4 | # 5 | # filters non-source files from a list of files, assuming one per line 6 | 7 | here=`dirname $0` 8 | here=${here:-.} 9 | 10 | set -e 11 | 12 | cleanup () { 13 | [ -f "$tmpfile" ] && rm -f "$tmpfile" 14 | } 15 | 16 | trap cleanup EXIT 17 | 18 | if [ "$1" == '-d' ]; then 19 | debug=y 20 | shift 21 | fi 22 | 23 | cvsignore=${ZDOTDIR:-~}/.cvsignore 24 | 25 | if ! [ -e $cvsignore ]; then 26 | cat <<'EOF' >&2 27 | source-only cannot run without ${cvsignore}! 28 | Please run: 29 | 30 | mrco cvs; mrst cvs 31 | EOF 32 | exit 1 33 | fi 34 | 35 | tmpfile=`mktemp /tmp/source-only.XXXXXXX` 36 | ( 37 | # We ignore every element no matter where it is in the path chain. 38 | # Probably the only way of improving performance further would be to 39 | # ditch the find | ignore pipeline in favour of something such as 40 | # Perl's File::Find which would integrate the find step with the 41 | # ignore step in order to prune the search tree. 42 | cat $cvsignore | \ 43 | $here/glob-to-re -u | \ 44 | sed 's/^/(^|\/)/; s/$/(\/|$)/' 45 | ) > $tmpfile 46 | 47 | if [ -n "$debug" ]; then 48 | cat $tmpfile 49 | else 50 | grep -vEf $tmpfile 51 | fi 52 | -------------------------------------------------------------------------------- /bin/split-by-boot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use File::Path; 6 | 7 | die "Usage: $0 <new output dir>\n" 8 | unless @ARGV && ! -e $ARGV[0]; 9 | my $dir = shift; 10 | mkdir($dir) or die "mkdir($dir): $!\n"; 11 | 12 | open_new("$dir/unknown"); 13 | my @buffer; # use split! 14 | my $BUFFER_SIZE = 10; # max lines in buffer 15 | 16 | while (<>) { 17 | if (/^(.+\d) (\S+) kernel: Linux version (\d\..+)/) { 18 | my ($when, $host, $version) = ($1, $2, $3); 19 | my ($ver, $builduid, $builddate) = 20 | $version =~ /(\d\.\S+) \((\S+?)\) \(.+\) #\d+ (.+)$/ 21 | or die "Couldn't parse version `$version'\n"; 22 | warn "$when: booted $ver ($builduid)\n"; 23 | $when =~ s/ / 0/; 24 | $when =~ s/\s+/-/g; 25 | my $outdir = "$dir/$builduid/$ver"; 26 | mkpath($outdir); 27 | while (@buffer && $buffer[0] !~ /syslogd.*restart/) { 28 | print OUT shift(@buffer); 29 | } 30 | open_new("$outdir/$when"); 31 | flush_buffer(); 32 | print OUT; 33 | } 34 | elsif (m!^(\d\d)\.(\d\d) (\d\d):(\d\d):(\d\d): Kernel,NOTICE: Arguments: \[\w+/zos\.conf\]$!) { 35 | my ($month, $day, $hour, $min, $sec) = ($1, $2, $3, $4, $5); 36 | flush_buffer(); 37 | open_new( 38 | } 39 | else { 40 | # If buffer is full, dequeue and print one line. 41 | print OUT shift(@buffer) unless @buffer < $BUFFER_SIZE; 42 | # By here, buffer cannot be full. 43 | push @buffer, $_; 44 | } 45 | } 46 | 47 | close(OUT); 48 | 49 | sub open_new { 50 | my ($outfile) = @_; 51 | die "$outfile already existed\n" if -e $outfile; 52 | open(OUT, ">$outfile") or die "open(>$outfile): $!\n"; 53 | } 54 | 55 | sub flush_buffer { 56 | print OUT @buffer; 57 | @buffer = (); 58 | } 59 | -------------------------------------------------------------------------------- /bin/syphon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | =head1 NAME 4 | 5 | syphon - removes lines from top of file 6 | 7 | =head1 SYNOPSIS 8 | 9 | $ syphon [-v] $regexp $src_filename > $outfile 10 | $ syphon -i [-v] $regexp $src_filename [ $removed_file ] 11 | 12 | =head1 DESCRIPTION 13 | 14 | Removes lines from the beginning of a file. Stops when a pattern is 15 | encountered (the first line matching the pattern is not removed). 16 | Outputs the file minus the lines syphoned off to STDOUT, unless C<-i> 17 | is specified, in which case the file is syphoned in place - the inode 18 | is preserved by filtering to a temporary file and then copying back 19 | over the original file. This means it will work with log files whose 20 | daemon opens them with C<O_APPEND>. If C<$removed_file> is specified, 21 | the removed lines will be written to that file. 22 | 23 | C<-v> turns on verbose output. 24 | 25 | =head1 EXAMPLE USAGE 26 | 27 | syphon -i '^... Jul .. ........ ... 2010' get-fbcal.log get-fbcal.log-2010-06 28 | 29 | Use of multi-syphon wrapper highly recommended! 30 | 31 | =cut 32 | 33 | use strict; 34 | use warnings; 35 | 36 | use File::Copy; 37 | use File::Temp qw/ :mktemp /; 38 | use Getopt::Long; 39 | 40 | (my $me = $0) =~ s,.*/,,; 41 | 42 | sub usage { 43 | warn @_, "\n" if @_; 44 | die <<EOF; 45 | Usage: $me [-v] \$regexp \$src_filename > \$outfile 46 | $me -i [-v] \$regexp \$src_filename [ \$removed_file ] 47 | EOF 48 | } 49 | 50 | my %opts; 51 | GetOptions(\%opts, 'in-place|i', 'verbose|v') or usage(); 52 | 53 | usage() unless @ARGV == 2 or ($opts{'in-place'} && @ARGV == 3); 54 | my ($re, $src, $removed) = @ARGV; 55 | my $compiled = qr/$re/; 56 | 57 | open(FILE, $src) or die "$me: open($src): $!\n"; 58 | if ($removed) { 59 | usage("$removed already exists.\n") if -e $removed; 60 | open(REMOVED, ">$removed") or die "$me: open(>$removed): $!\n"; 61 | } 62 | 63 | my ($temp_fh, $temp_fn) = get_dest(); 64 | 65 | remove_lines(); 66 | warn "Line removal finished.\n" 67 | if $opts{'in-place'} && $opts{verbose}; 68 | print $temp_fh $_; 69 | print $temp_fh $_ while <FILE>; 70 | close(FILE); 71 | 72 | if ($opts{'in-place'}) { 73 | warn "Remainder written to $temp_fn.\n" 74 | if $opts{verbose}; 75 | close($temp_fh); 76 | # print "Written to $temp_fn\n"; 77 | copy $temp_fn, $src; 78 | unlink $temp_fn; 79 | } 80 | 81 | sub remove_lines { 82 | if ($removed) { 83 | while (<FILE>) { 84 | last if /$compiled/; 85 | print REMOVED $_; 86 | } 87 | } 88 | else { 89 | while (<FILE>) { 90 | last if /$compiled/; 91 | } 92 | } 93 | } 94 | 95 | sub get_dest { 96 | return (\*STDOUT) unless $opts{'in-place'}; 97 | return mkstemp( "/tmp/syphon-XXXXXXX" ); 98 | } 99 | 100 | =head1 SEE ALSO 101 | 102 | L<csplit(1)>, which I only discovered after writing this :-( 103 | I needed the "in-place" feature though. 104 | 105 | =head1 VERSION 106 | 107 | $Id$ 108 | 109 | =head1 LICENSE 110 | 111 | Copyright (c) 2003 Adam Spiers <adam@spiers.net> 112 | 113 | This program is free software: you can redistribute it and/or modify 114 | it under the terms of the GNU General Public License as published by 115 | the Free Software Foundation, either version 3 of the License, or 116 | (at your option) any later version. 117 | 118 | This program is distributed in the hope that it will be useful, 119 | but WITHOUT ANY WARRANTY; without even the implied warranty of 120 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 121 | GNU General Public License for more details. 122 | 123 | You should have received a copy of the GNU General Public License 124 | along with this program. If not, see <http://www.gnu.org/licenses/>. 125 | 126 | =cut 127 | -------------------------------------------------------------------------------- /bin/tailfgrep: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # tailfgrep -- monitor a file a la tail -f, looking for a given regexp 4 | # Copyright (c) 1999 Adam Spiers <adam@spiers.net> 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 | 19 | # TODO: 20 | # - extend to multiple patterns (one for each file?) 21 | # - include more options from tail (e.g. -n) and grep (e.g. -i) 22 | 23 | use strict; 24 | use warnings; 25 | 26 | use Getopt::Long; 27 | 28 | my ($quiet, $inverse, $match) = (0, 0, 0); 29 | GetOptions( 30 | "quiet|q" => \$quiet, 31 | "inverse|v" => \$inverse, 32 | "match|m" => \$match, 33 | ); 34 | 35 | unless (@ARGV) { 36 | die <<EOF; 37 | Usage: tailfgrep [ options ] <Perl regexp> <file1> [ <file2> [ <file3> ... ] ] 38 | -m, --match -- echo everything to STDOUT, exit when first match found 39 | -q, --quiet -- quiet mode, same as grep -q; don't print matches, 40 | exit when first match found 41 | -v, --inverse -- inverse mode (print lines which don't match) 42 | EOF 43 | } 44 | 45 | my ($re, @files) = @ARGV; 46 | 47 | my %fh = (); 48 | open_files(); 49 | 50 | $| = 1; 51 | 52 | my $last_file = ''; 53 | 54 | while (1) { 55 | FILE: 56 | foreach my $file (@files) { 57 | my $fh = $fh{$file}; 58 | while (defined($_ = <$fh>)) { 59 | if ($quiet) { 60 | exit 0 if match($_); 61 | } 62 | elsif ($match) { 63 | output_line($file); 64 | exit 0 if match($_); 65 | } 66 | else { 67 | output_line($file) if match($_); 68 | } 69 | } 70 | seek($fh, 0, 1); # clear EOF 71 | } 72 | sleep 1; 73 | } 74 | 75 | close_files(); 76 | 77 | sub open_files { 78 | if (! @files && -t 1) { 79 | push @files, '-'; 80 | } 81 | 82 | foreach my $file (@files) { 83 | if ($file eq '-') { 84 | $fh{$file} = *STDIN; 85 | next; 86 | } 87 | 88 | -f $file or die "$file isn't a file.\n"; 89 | local *FH; 90 | open(FH, $file) or die "Couldn't open $file: $!\n"; 91 | seek(FH, 0, 2); 92 | $fh{$file} = *FH; 93 | } 94 | } 95 | 96 | sub close_files { 97 | foreach my $file (@files) { 98 | my $fh = $fh{$file}; 99 | # warn "closing $file / $fh\n"; 100 | close($fh); 101 | } 102 | } 103 | 104 | sub match { 105 | my ($line) = @_; 106 | return ($line =~ /$re/) ^ $inverse; 107 | } 108 | 109 | sub output_line { 110 | my ($file) = @_; 111 | 112 | $file = 'STDIN' if $file eq '-'; 113 | 114 | if (@files > 1) { 115 | if ($file ne $last_file) { 116 | print "\n==> $file <==\n\n"; 117 | } 118 | print; 119 | $last_file = $file; 120 | } 121 | else { 122 | print; 123 | $last_file = $file; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /bin/tf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me=`basename $0` 4 | 5 | usage () { 6 | cat <<EOF >&2 7 | Usage: $me FILE1 [FILE2 ...] 8 | EOF 9 | exit 1 10 | } 11 | 12 | if [ "$1" == -h ] || [ "$1" == --help ] || [ $# = 0 ]; then 13 | usage 14 | fi 15 | 16 | if [ $# = 1 ]; then 17 | exec less +F "$1" 18 | #exec tailf "$1" 19 | else 20 | exec tail -f "$@" 21 | fi 22 | -------------------------------------------------------------------------------- /bin/tfs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | me=`basename $0` 4 | 5 | usage () { 6 | cat <<EOF >&2 7 | Usage: $me FILE1 [FILE2 ...] 8 | EOF 9 | exit 1 10 | } 11 | 12 | if [ "$1" == -h ] || [ "$1" == --help ] || [ $# = 0 ]; then 13 | usage 14 | fi 15 | 16 | if [ $# = 1 ]; then 17 | exec less +F -S "$1" 18 | else 19 | echo "$me: FIXME: cut breaks tail -f, can't emulate less -S" >&2 20 | #exec tail -f "$@" | cut -c 1-$COLUMNS 21 | exec tail -f "$@" 22 | fi 23 | -------------------------------------------------------------------------------- /bin/tl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Try to get in the right habit since jl is better for this use case 4 | if [ -z "$1" ]; then 5 | echo >&2 "Use jl instead for viewing system journal" 6 | exit 1 7 | fi 8 | 9 | if which lnav >&/dev/null; then 10 | lnavf "$@" 11 | else 12 | tf "$@" 13 | fi 14 | -------------------------------------------------------------------------------- /bin/tre: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # tree with colour 4 | exec tree -C "$@" 5 | -------------------------------------------------------------------------------- /bin/trel: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # tre but like ls -l 4 | exec tre -ugsp "$@" 5 | -------------------------------------------------------------------------------- /bin/trim-lines: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $trim_to = ($ENV{COLUMNS} || 72) - 2; 7 | 8 | my $DEBUG = 0; 9 | 10 | sub debug { 11 | warn @_, "\n" if $DEBUG; 12 | } 13 | 14 | sub output { 15 | my $out = shift; 16 | if ($DEBUG) { 17 | $out =~ s/\e/\\e/g; 18 | print "Outputting [$out]\n"; 19 | } 20 | else { 21 | print $out; 22 | } 23 | } 24 | 25 | debug("Trimming to $trim_to columns"); 26 | 27 | while (<>) { 28 | chomp; 29 | my @segments = split /(\e[[\d;]*m)/, $_; 30 | 31 | my $offset = 0; 32 | foreach my $segment (@segments) { 33 | if (substr($segment, 0, 1) eq "\e") { 34 | output($segment, 1); 35 | next; 36 | } 37 | debug("Considering [$segment]"); 38 | my $len = length $segment; 39 | my $up_to = $offset + $len; 40 | my $excess = $up_to - $trim_to; 41 | if ($excess > 0) { 42 | debug("$offset + $len == $up_to > $trim_to by $excess"); 43 | output(substr($segment, 0, length($segment) - $excess)); 44 | last; 45 | } 46 | $offset += length $segment; 47 | output($segment); 48 | debug("offset now $offset"); 49 | } 50 | debug("=" x $trim_to); 51 | print "\n" unless $DEBUG; 52 | } 53 | -------------------------------------------------------------------------------- /bin/trim-whitespace: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Long; 7 | 8 | Getopt::Long::Configure('bundling'); 9 | 10 | my %opts = ( verbosity => 1 ); 11 | GetOptions( 12 | \%opts, 13 | 'help|h', 14 | 'leading|l', 'trailing|t', 15 | ) or usage(); 16 | usage() if $opts{help}; 17 | 18 | sub usage { 19 | warn @_, "\n" if @_; 20 | 21 | (my $ME = $0) =~ s,.*/,,; 22 | 23 | die <<EOUSAGE; 24 | Usage: $ME [options] 25 | Trims leading/trailing whitespace from each line. 26 | 27 | Options: 28 | -l, --leading Only trim leading whitespace 29 | -t, --trailing Only trim trailing whitespace 30 | -h, --help Show this help 31 | EOUSAGE 32 | } 33 | 34 | if (! $opts{leading} && ! $opts{trailing}) { 35 | # Default to trimming both if no options specified. 36 | $opts{leading} = $opts{trailing} = 1; 37 | } 38 | 39 | my $to_trim = qr/[ \t]+/; 40 | 41 | while (<>) { 42 | s/^$to_trim// if $opts{leading}; 43 | s/$to_trim$// if $opts{trailing}; 44 | print; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /bin/tty-colour-diff: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -t 1 ]; then 4 | # connected to a tty => use glorious technicolour and paging 5 | # This gawk -f/which combination makes us platform-agnostic by relying on $PATH twice. 6 | exec gawk -f `which colour-diff-output` | diff-less "$@" 7 | else 8 | # probably piping to a file, use black and white 9 | exec cat 10 | fi 11 | -------------------------------------------------------------------------------- /bin/udate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -wl 2 | 3 | use POSIX qw(strftime); 4 | 5 | my $utc; 6 | 7 | if (@ARGV and $ARGV[0] =~ /^-u|--utc$/) { 8 | shift @ARGV; 9 | $utc = 1; 10 | } 11 | 12 | my $time = $ARGV[0] || time; 13 | 14 | if ($utc) { 15 | print strftime "%a %e %b %H:%M:%S %Y UTC +0000", gmtime($time); 16 | #print scalar gmtime($time); 17 | } 18 | else { 19 | print strftime "%a %e %b %H:%M:%S %Y %Z %z", localtime($time); 20 | #print scalar localtime($time); 21 | } 22 | -------------------------------------------------------------------------------- /bin/ujc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Poettering's info on --user and systemd-journal gid: 4 | # 5 | # https://lists.freedesktop.org/archives/systemd-devel/2016-October/037554.html 6 | # 7 | # if ! groups | grep -q systemd-journal; then 8 | # echo >&2 "Need to be in systemd-journal group; aborting!" 9 | # exit 1 10 | # fi 11 | 12 | journalctl --user "$@" 13 | -------------------------------------------------------------------------------- /bin/ujcf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # See notes in ujcfu about not using --user via ujc 4 | 5 | ujc -f "$@" 6 | -------------------------------------------------------------------------------- /bin/ujcfu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Note that we omit --user here, because for some weird reason it 4 | # doesn't always work with --user. E.g. once on ionian I saw it 5 | # showing "No journal files were found." until I restarted 6 | # systemd-journald.service. This *might* have been because it was 7 | # started without /var/log/journal existing, therefore the default of 8 | # Storage=auto in /etc/systemd/journald.conf chose volatile storage 9 | # (see journald.conf(5) man page). 10 | # 11 | # https://unix.stackexchange.com/questions/109490/where-is-why-is-there-no-log-for-normal-user-systemd-services 12 | # 13 | # points to: 14 | # 15 | # https://lists.freedesktop.org/archives/systemd-devel/2016-October/037554.html 16 | # 17 | # where Poettering explains that persistent logging is needed for this 18 | # to work. However he also seemed to suggest that membership of the 19 | # systemd-journal group should have been sufficient, but apparently it 20 | # wasn't in the above scenario. 21 | # 22 | # Either way it seems that it always works with just --user-unit. 23 | 24 | jcf --user-unit "$@" 25 | -------------------------------------------------------------------------------- /bin/ujcu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # See notes in ujcfu about not using --user via ujc 4 | 5 | jc --user-unit "$@" 6 | -------------------------------------------------------------------------------- /bin/ujl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | jl --user "$@" 4 | -------------------------------------------------------------------------------- /bin/ujlu: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # See notes in ujcfu about not using --user via ujc 4 | 5 | jl --user-unit "$@" 6 | -------------------------------------------------------------------------------- /bin/umnt-initrd: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [[ "$OSTYPE" != linux* ]]; then 6 | echo "Not on a Linux box; aborting." 7 | exit 1 8 | fi 9 | 10 | if [[ `id -u` != 0 ]]; then 11 | echo "Not root; aborting." 12 | exit 1 13 | fi 14 | 15 | if [[ $# > 1 ]]; then 16 | echo "Usage: $0 [ <initrd image mountpoint> ]" 17 | exit 1 18 | fi 19 | 20 | dir=${1:-mnt:initrd.img} 21 | dst=initrd.img.new 22 | 23 | if ! [[ -d $dir ]]; then 24 | echo "$1 isn't a valid directory; aborting." 25 | exit 1 26 | fi 27 | 28 | abs_dir=`/home/aspiers/bin/shortcuts/abs $dir` 29 | 30 | if ! mount | grep -q $abs_dir; then 31 | echo "$abs_dir isn't mounted; aborting." 32 | exit 1 33 | fi 34 | 35 | if [[ -e $dst ]]; then 36 | echo "$dst already exists! Aborting." 37 | exit 1 38 | fi 39 | 40 | # hairy quoting alert! 41 | img=`mount | awk "/ on ${abs_dir//\//\\/} /"' { print $1 }'` 42 | #echo "Image is $img" 43 | 44 | umount $dir 45 | gzip -9 $img 46 | mv $img.gz $dst 47 | echo "New image is $dst" 48 | -------------------------------------------------------------------------------- /bin/un: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# = 0 ]; then 4 | uname -a 5 | else 6 | uname "$@" 7 | fi 8 | -------------------------------------------------------------------------------- /bin/unindent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # http://stackoverflow.com/questions/3772864/how-do-i-remove-leading-whitespace-chars-from-ruby-heredoc 4 | 5 | def strip_indent(string) 6 | if mindent = string.scan(/^[ \t]*/).min_by(&:length) 7 | string.gsub /^#{mindent}/, '' 8 | end 9 | end 10 | 11 | puts strip_indent(ARGF.read) 12 | -------------------------------------------------------------------------------- /bin/up: -------------------------------------------------------------------------------- 1 | unpack -------------------------------------------------------------------------------- /bin/up-since: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -wl 2 | 3 | use strict; 4 | 5 | chomp(my $OS = `uname -s`); 6 | die "$0: OS is $OS not Linux\n" unless $OS eq 'Linux'; 7 | 8 | # also awk '/btime/{print $2}' /proc/stat 9 | my ($a, $b) = split /\s+/, `cat /proc/uptime`; 10 | print scalar localtime(time - $a); 11 | 12 | -------------------------------------------------------------------------------- /bin/url_handler.sh: -------------------------------------------------------------------------------- 1 | url-handler -------------------------------------------------------------------------------- /bin/usc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | systemctl --user "$@" 4 | -------------------------------------------------------------------------------- /bin/usca: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Crazy that there's no better way to do this. 4 | find ~/.config/systemd/user/ -name "*.service" -printf '%f\0' | \ 5 | xargs -0 systemctl --user list-units --all 6 | -------------------------------------------------------------------------------- /bin/uuid: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | uuidgen | xclip -r -selection clipboard 4 | -------------------------------------------------------------------------------- /bin/viz: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | me="`basename $0`" 4 | 5 | if [ $# != 1 ] || ! [ -e "$1" ]; then 6 | echo "Usage: $me <file>" 7 | exit 1 8 | fi 9 | 10 | dir="`dirname $1`" 11 | file="`basename $1`" 12 | orig_dir="`pwd`" 13 | 14 | if ! viz_tmpdir=`mktemp -d /tmp/$me.XXXXXXXX` || ! [ -d "$viz_tmpdir" ]; then 15 | echo "mktemp failed: $!" 16 | exit 1 17 | fi 18 | 19 | cleanup () { 20 | [ -n "$viz_tmpdir" ] && rm -rf "$viz_tmpdir" 21 | } 22 | 23 | trap cleanup EXIT 24 | 25 | if ! co -l "$dir/$file"; then 26 | echo "Checkout failed; aborting." >&2 27 | exit 1 28 | fi 29 | 30 | tmpfile="$viz_tmpdir/$file" 31 | cp "$dir/$file" "$tmpfile" 32 | editor="${EDITOR:-${VISUAL:-vi}}" 33 | 34 | validate () { 35 | if [ -x "$dir/.vizrc" ]; then 36 | echo "Testing validity of changes ... " 37 | "$dir/.vizrc" "$tmpfile" "$dir" "$file" "$viz_tmpdir" 38 | return $? 39 | fi 40 | return 0 41 | } 42 | 43 | trap 'echo -e "\nNo cheating now!"' INT 44 | 45 | $editor "$tmpfile" 46 | 47 | while [ 1 = 1 ]; do 48 | changed= 49 | cmp -s "$dir/$file" "$tmpfile" || changed=y 50 | [ -z "$changed" ] && break 51 | 52 | if validate "$tmpfile"; then 53 | echo "Changes validated OK." 54 | validates=y 55 | else 56 | echo "Changes failed validation!" 57 | validates= 58 | fi 59 | 60 | replied= 61 | while [ -z "$replied" ]; do 62 | if [ -n "$validates" ]; then 63 | read -n 1 -p "Re-edit, diff, check in, or abandon [r/d/c/a]? " reply 64 | else 65 | read -n 1 -p "Re-edit, diff, or abandon [r/d/a]? " reply 66 | fi 67 | case "$reply" in 68 | a) changed= 69 | echo 70 | # get me outta here 71 | break 10 72 | ;; 73 | r) replied=y ; echo ;; 74 | c) echo 75 | if [ -n "$validates" ]; then 76 | # get me outta here 77 | break 10 78 | fi 79 | ;; 80 | d) echo; diff -u "$dir/$file" "$tmpfile" | less ;; 81 | *) echo ;; 82 | esac 83 | done 84 | 85 | $editor "$tmpfile" 86 | done 87 | 88 | if [ -z "$changed" ]; then 89 | co -u -f "$dir/$file" 90 | exit 0 91 | fi 92 | 93 | cp "$tmpfile" "$dir" # rather than mv, preserves permissions 94 | ci -u "$dir/$file" 95 | -------------------------------------------------------------------------------- /bin/waitpid: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pid=$1 4 | 5 | while [ -d /proc/$1 ]; do 6 | sleep 1 7 | done 8 | -------------------------------------------------------------------------------- /bin/waitproc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $( pgrep -c "$@" ) -eq 0 ]; then 4 | echo "pgrep $@ didn't find any matching pids; aborting." >&2 5 | exit 1 6 | elif [ $( pgrep -c "$@" ) -ne 1 ]; then 7 | echo "pgrep $@ found more than one matching pid:" >&2 8 | pgrep -l "$@" | sed 's/^/ /' >&2 9 | echo "Aborting." >&2 10 | exit 1 11 | fi 12 | 13 | # FIXME: race condition here 14 | waitpid `pgrep "$@"` 15 | -------------------------------------------------------------------------------- /bin/wchan: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec ps -O wchan:25 "$@" 4 | -------------------------------------------------------------------------------- /bin/wd: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec watch -d "$@" 4 | -------------------------------------------------------------------------------- /bin/wdf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exec watchdiff "$@" 4 | -------------------------------------------------------------------------------- /bin/wget-monitor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # wget-monitor -- simple URL monitor 4 | # 5 | # Stick a list of URLs in ~/.wget-monitor, one per line, (blank lines 6 | # and comment lines with '#' allowed) for wget to retrieve. First 7 | # invocation fetches the URLs into a local cache; subsequent 8 | # invocations diff the online version against the cache. 9 | # 10 | # Copyright (c) 2003 Adam Spiers <adam@spiers.net> 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License as published by 14 | # the Free Software Foundation, either version 3 of the License, or 15 | # (at your option) any later version. 16 | # 17 | # This program is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | # GNU General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU General Public License 23 | # along with this program. If not, see <http://www.gnu.org/licenses/>. 24 | 25 | use strict; 26 | use warnings; 27 | 28 | use File::Basename; 29 | use File::Path; 30 | use File::Temp 'tempdir'; 31 | 32 | open(CFG, "$ENV{HOME}/.wget-monitor") 33 | or die "$0: $!\n"; 34 | 35 | my $cache = "$ENV{HOME}/.wget-monitor-cache"; 36 | -d $cache or mkdir $cache; 37 | 38 | my $tempdir = tempdir("/tmp/wget-monitor-XXXXXXX", CLEANUP => 1); 39 | 40 | my $changes = 0; 41 | while (<CFG>) { 42 | next if /^\s*#/ || /^\s*$/; 43 | 44 | chomp; 45 | 46 | m!^((http|ftp):)//! or die "Weird line $.:\n$_\n"; 47 | my $proto = $1; 48 | 49 | chdir $tempdir or die "chdir($tempdir) failed: $!\n"; 50 | my $wget = `wget -nv -x "$_" 2>&1`; 51 | my ($path) = $wget =~ /-> "(.+)"/ 52 | or die "Weird output from wget:\n$wget\n"; 53 | my $new = "$tempdir/$path"; 54 | my $old = "$cache/$proto/$path"; 55 | 56 | if (-e $old) { 57 | my $diff = `diff -u "$old" "$new"`; 58 | if ($diff) { 59 | $changes++; 60 | $diff =~ s!^--- $cache/!--- !m; 61 | print $diff; 62 | } 63 | } 64 | else { 65 | my $dir = dirname($old); 66 | mkpath($dir, 0, 0700) or die "mkpath($dir) failed: $!\n"; 67 | } 68 | 69 | rename $new, $old 70 | or warn "rename($new, $old) failed: $!\n"; 71 | } 72 | 73 | exit $changes; 74 | -------------------------------------------------------------------------------- /bin/whenup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -lt 1 ]; then 4 | echo "Usage: $0 [-a] <host>" 5 | exit 1 6 | fi 7 | 8 | if [ "$1" == '-a' ]; then 9 | alertme=yes 10 | shift 11 | fi 12 | 13 | host="$1" 14 | shift 15 | 16 | up= 17 | case "$OSTYPE" in 18 | solaris*) ping -s "$host" | tailfgrep -q 'bytes from' && up=yes 19 | ;; 20 | 21 | # FreeBSD and Linux 22 | *) ping "$host" | tailfgrep -q 'bytes from' && up=yes 23 | ;; 24 | esac 25 | 26 | if [ -n "$up" ]; then 27 | if [ -n "$alertme" ]; then 28 | alertme "$host is pingable" >&/dev/null 29 | fi 30 | exit 0 31 | else 32 | exit 1 33 | fi 34 | -------------------------------------------------------------------------------- /bin/wl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Which Less - locate an executable via which(1) and then run less(1) on it 4 | 5 | if [ $# = 0 ]; then 6 | # get usage 7 | which 8 | else 9 | if which "$@" >/dev/null; then 10 | if which bat >/dev/null 2>&1; then 11 | bat `which "$@"` 12 | else 13 | # -F is --quit-if-one-screen 14 | less -F `which "$@"` 15 | fi 16 | else 17 | which "$@" 18 | fi 19 | fi 20 | -------------------------------------------------------------------------------- /bin/xauth-user: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | if [ $# = 0 ] || [ "$1" = '-h' ] || [ "$1" = '--help' ]; then 6 | echo "Usage: $0 <user1 to authorise> [ <user2> ... ]" 7 | exit 0 8 | fi 9 | 10 | if [ -z "$DISPLAY" ]; then 11 | echo "\$DISPLAY not set; aborting." >&2 12 | exit 1 13 | fi 14 | 15 | # Not sure what to do here. Sometimes we get two results: 16 | # one for MIT-MAGIC-COOKIE-1 and one for XDM-AUTHORIZATION-1. 17 | # In that case, XDM-AUTHORIZATION-1 seems to be the right one 18 | # (presumably because xdm/gdm/kdm was used to login). 19 | cookie="`xauth list $DISPLAY | tail -n 1`" 20 | 21 | if [ -z "$cookie" ]; then 22 | echo "xauth list $DISPLAY failed to return a cookie" >&2 23 | exit 1 24 | fi 25 | 26 | for user in "$@"; do 27 | echo "Adding '$cookie' for user $user" 28 | su -c "set -x; unset XAUTHORITY; xauth add $cookie" "$user" 29 | done 30 | -------------------------------------------------------------------------------- /bin/zdate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from datetime import datetime 5 | 6 | if len(sys.argv) != 2: 7 | print("Usage: zdate <timestamp>") 8 | sys.exit(1) 9 | 10 | try: 11 | timestamp = float(sys.argv[1]) 12 | except ValueError: 13 | print("Invalid timestamp. Please provide a Unix timestamp (integer)") 14 | sys.exit(1) 15 | 16 | if timestamp > 1000000000000: 17 | timestamp /= 1000 18 | 19 | epoch_time = datetime.utcfromtimestamp(timestamp) 20 | formatted_time = epoch_time.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + 'Z' 21 | print(formatted_time) 22 | -------------------------------------------------------------------------------- /bin/zipseqs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Getopt::Long; 7 | 8 | my %opts; 9 | GetOptions(\%opts, 'prefixes|p', 'format|f=s', 'eof|e') or usage(); 10 | 11 | sub usage { 12 | die <<EOF; 13 | Usage: $0 file1 file2 [...] 14 | $0 [ -p | --prefixes ] prefix1 file1 prefix2 file2 [...] 15 | $0 [ -f | --format=STR ] file1 file2 [...] 16 | -e, --eof Abort as soon as EOF is reached on any file. 17 | 18 | Take two or more sequences and 'zip' them together in the functional 19 | programming sense. Defaults to one item per line. -p prefixes each 20 | item with a specified prefix. -f allows an arbitrary output format, 21 | with each '%s' substituted for an item in the zipped sequence, e.g. 22 | the following are almost equivalent: 23 | 24 | $0 -p prefix1 file1 prefix2 file2 25 | $0 -f 'prefix1 %s\nprefix2 %s\n' file1 file2 26 | 27 | except that the former would stop intelligently if file2 ran out of 28 | items before file1 - there's no obvious general way of trimming a format 29 | string intelligently when one list runs out before another. 30 | EOF 31 | } 32 | 33 | usage() unless @ARGV; 34 | 35 | my (@files, %prefixes); 36 | if ($opts{prefixes}) { 37 | usage() unless @ARGV % 2 == 0; 38 | while (@ARGV) { 39 | my $prefix = shift; 40 | my $file = shift; 41 | push @files, $file; 42 | $prefixes{$file} = $prefix; 43 | } 44 | #$format = map "$prefixes{$_} %s\n", @files; 45 | } 46 | else { 47 | @files = @ARGV; 48 | } 49 | 50 | $opts{format} =~ s/(\\([abefnrt]|x\d\d|0\d{2,3}))/qq["$1"]/gee if exists $opts{format}; 51 | 52 | my %fh; 53 | foreach my $file (@files) { 54 | open($fh{$file}, $file) or die "open($file) failed: $!\n"; 55 | } 56 | 57 | my %eof; 58 | 59 | OUTER: 60 | while (1) { 61 | my $out = $opts{format}; 62 | foreach my $i (0 .. $#files) { 63 | my $file = $files[$i]; 64 | my $line = get_line($file); 65 | unless (defined $line) { 66 | last OUTER if $opts{eof}; 67 | next; 68 | } 69 | if (exists $opts{format}) { 70 | $out =~ s/%s/$line/; 71 | } 72 | else { 73 | print $prefixes{$file}, ' ' if $opts{prefixes}; 74 | print "$line\n" if $line; 75 | } 76 | } 77 | 78 | # prune files which have reached EOF 79 | @files = grep ! $eof{$_}, @files; 80 | 81 | # print "@files\n"; 82 | 83 | last if @files == 0; 84 | 85 | if ($opts{format}) { 86 | $out =~ s/%s/EOF/g; 87 | print $out; 88 | } 89 | 90 | # sleep 1; 91 | } 92 | 93 | sub get_line { 94 | my ($file) = @_; 95 | return undef if $eof{$file}; 96 | my $fh = $fh{$file}; 97 | my $line = <$fh>; 98 | if (defined $line) { 99 | chomp $line; 100 | } 101 | else { 102 | $eof{$file}++; 103 | } 104 | return $line; 105 | } 106 | -------------------------------------------------------------------------------- /lib/fs-trend.gnuplot: -------------------------------------------------------------------------------- 1 | 2 | set xdata time 3 | # set timefmt "%H:%M:%S" 4 | # set xrange ["14:43:20":"15:43:20"] 5 | set timefmt "%s" 6 | set xrange ["1211550201":"1211561235"] 7 | set format x "%T" 8 | set yrange [0:] 9 | #set format y "%T" 10 | 11 | plot '/tmp/var.du' using 1:4 with linespoints 12 | 13 | pause -1 14 | -------------------------------------------------------------------------------- /lib/libhooks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rebuild_config () { 4 | config="$1" 5 | hookdir="$2" 6 | if [ $# != 2 ]; then 7 | echo "BUG: rebuild_config called by $0 with incorrect # of parameters" >&2 8 | return 1 9 | fi 10 | 11 | magic_string="# Autogenerated from $0 via rebuild_config" 12 | magic_string_re="^# Autogenerated from ($0|.* via rebuild_config)" 13 | 14 | if [ -L "$config" ]; then 15 | echo "Error: $config is a symlink; won't overwrite." >&2 16 | return 1 17 | fi 18 | 19 | if [ -e "$config" ]; then 20 | if ! [ -s "$config" ]; then 21 | echo "# $config is empty" 22 | elif ! grep -Eq "$magic_string_re" "$config"; then 23 | cat <<EOF >&2 24 | Error: can't find '$magic_string_re' in $config 25 | Presumably hand-written so won't overwrite; please break into parts. 26 | EOF 27 | return 1 28 | fi 29 | fi 30 | 31 | echo "# Rebuilding $config ..." 32 | 33 | cat <<EOF > "$config" 34 | # Autogenerated from $0 via rebuild_config at `date` 35 | 36 | EOF 37 | 38 | # Ensure we have $ZDOT_FIND_HOOKS; if this is being invoked from 39 | # be.sh then we probably don't. 40 | source $ZDOTDIR/.shared_env 41 | 42 | # sort by filename not by path 43 | $ZDOT_FIND_HOOKS "$hookdir" | \ 44 | sed 's/\(.\+\)\/\(.\+\)/\2 -%- \1\/\2/' | \ 45 | sort -k1 | \ 46 | sed 's/.* -%- //' | \ 47 | while read conf; do 48 | echo "# Appending $conf" 49 | # Allow for executable hooks, for generating content dynamically, 50 | # triggered by including a magic cookie in the hook file. 51 | if grep -q '%% Executable hook %%' "$conf"; then 52 | echo "# Output of $conf follows:" >> "$config" 53 | if ! "$conf" >> "$config"; then 54 | echo >&2 "$conf failed; aborting." 55 | exit 1 56 | fi 57 | else 58 | echo "# Include of $conf follows:" >> "$config" 59 | cat "$conf" >> "$config" 60 | fi 61 | echo >> "$config" 62 | done 63 | } 64 | -------------------------------------------------------------------------------- /lib/libhost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | read_localhost_nickname () { 4 | HOST_NAME_FILE=$ZDOTDIR/.localhost-nickname 5 | [ -f "$HOST_NAME_FILE" ] && localhost_nickname="$(<$HOST_NAME_FILE)" 6 | [ -n "$localhost_nickname" ] && return 0 7 | 8 | echo "Put host nickname in $HOST_NAME_FILE" >&2 9 | return 1 10 | } 11 | -------------------------------------------------------------------------------- /lib/liblogging.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | fatal () 4 | { 5 | error "$@" 6 | } 7 | 8 | # Broken out as special case for log() failure. Ordinarily you 9 | # should just use error() to terminate. 10 | _die () 11 | { 12 | echo "ERROR: $@" >&2 13 | exit 1 14 | } 15 | 16 | error () 17 | { 18 | log "ERROR: $@" 19 | _die "$@" 20 | } 21 | 22 | warn () 23 | { 24 | log "WARNING: $@" 25 | echo "WARNING: $@" >&2 26 | } 27 | 28 | log () 29 | { 30 | if [ -z "$LOG_FILE" ]; then 31 | #_die "\$LOG_FILE was not set - aborting" 32 | return 33 | fi 34 | echo "$*" >> "$LOG_FILE" || _die "Can't append to $LOG_FILE - aborting" 35 | } 36 | -------------------------------------------------------------------------------- /lib/libuid.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ensure_uid_root () { 4 | if [ `id -u` != 0 ]; then 5 | echo "Not root; aborting." >&2 6 | exit 1 7 | fi 8 | } 9 | 10 | ensure_uid_non_root () { 11 | if [ `id -u` = 0 ]; then 12 | echo "Must not be root; aborting." >&2 13 | exit 1 14 | fi 15 | } 16 | -------------------------------------------------------------------------------- /lib/perl5/Sh.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Test::More tests => 9; 7 | 8 | BEGIN { use_ok('Sh', qw(abs_path_by_chdir abs_path_by_chasing)) } 9 | 10 | diag("Sh loaded from $INC{'Sh.pm'}"); 11 | 12 | my @expected = ( 13 | '/' => '/', 14 | '//' => '/', 15 | '/tmp' => '/tmp', 16 | '/nonexistent' => '/nonexistent', 17 | '/tmp/..' => '/', 18 | '/var/adm' => '/var/adm', 19 | '/var/log/messages' => '/var/log/messages', 20 | '/var/tmp/../log/messages' => '/var/log/messages', 21 | '/var/../tmp' => '/tmp', 22 | ); 23 | 24 | while (@expected) { 25 | my $input = shift @expected; 26 | my $expected = shift @expected; 27 | 28 | is(abs_path_by_chdir($input), $expected, "abs_path_by_chdir($input)"); 29 | is(abs_path_by_chasing($input), $expected, "abs_path_by_chasing($input)"); 30 | } 31 | -------------------------------------------------------------------------------- /t/.gitignore: -------------------------------------------------------------------------------- 1 | trash directory*/ 2 | test-results/ 3 | -------------------------------------------------------------------------------- /t/Makefile: -------------------------------------------------------------------------------- 1 | # Run tests 2 | # 3 | # Copyright (c) 2005 Junio C Hamano 4 | # 5 | 6 | #GIT_TEST_OPTS=--verbose --debug 7 | SHELL_PATH ?= $(SHELL) 8 | PERL_PATH ?= /usr/bin/perl 9 | TAR ?= $(TAR) 10 | RM ?= rm -f 11 | PROVE ?= prove 12 | DEFAULT_TEST_TARGET ?= test 13 | 14 | # Shell quote; 15 | SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) #' 16 | 17 | T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) 18 | 19 | all: $(DEFAULT_TEST_TARGET) 20 | 21 | test: pre-clean $(TEST_LINT) 22 | $(MAKE) aggregate-results-and-cleanup 23 | 24 | prove: pre-clean $(TEST_LINT) 25 | @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS) 26 | $(MAKE) clean-except-prove-cache 27 | 28 | $(T): 29 | @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) 30 | 31 | pre-clean: 32 | $(RM) -r test-results 33 | 34 | clean-except-prove-cache: 35 | $(RM) -r 'trash directory'.* test-results 36 | 37 | clean: clean-except-prove-cache 38 | $(RM) .prove 39 | 40 | aggregate-results-and-cleanup: $(T) 41 | $(MAKE) aggregate-results 42 | $(MAKE) clean 43 | 44 | aggregate-results: 45 | for f in test-results/t*-*.counts; do \ 46 | echo "$$f"; \ 47 | done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh 48 | 49 | test-results: 50 | mkdir -p test-results 51 | 52 | smoke: test-results/git-smoke.tar.gz 53 | 54 | .PHONY: pre-clean $(T) aggregate-results clean 55 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/a/b/newer-in-src: -------------------------------------------------------------------------------- 1 | older 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/a/b/older-in-src: -------------------------------------------------------------------------------- 1 | newer 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/a/b/only-dst: -------------------------------------------------------------------------------- 1 | only-dst 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/a/b/same: -------------------------------------------------------------------------------- 1 | same 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/c/newer-in-src: -------------------------------------------------------------------------------- 1 | older 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/c/older-in-src: -------------------------------------------------------------------------------- 1 | newer 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/c/only-dst: -------------------------------------------------------------------------------- 1 | only-dst 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/dst/c/same: -------------------------------------------------------------------------------- 1 | same 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/a/b/newer-in-src: -------------------------------------------------------------------------------- 1 | newer 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/a/b/older-in-src: -------------------------------------------------------------------------------- 1 | older 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/a/b/only-src: -------------------------------------------------------------------------------- 1 | only-src 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/a/b/same: -------------------------------------------------------------------------------- 1 | same 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/c/newer-in-src: -------------------------------------------------------------------------------- 1 | newer 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/c/older-in-src: -------------------------------------------------------------------------------- 1 | older 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/c/only-src: -------------------------------------------------------------------------------- 1 | only-src 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/c/same: -------------------------------------------------------------------------------- 1 | same 2 | -------------------------------------------------------------------------------- /t/mv-merge/mv-merge-test.vanilla/src/d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspiers/shell-env/8a54c5e45ba72a42943dd30f9c713c6c7921837f/t/mv-merge/mv-merge-test.vanilla/src/d --------------------------------------------------------------------------------