diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2016-08-09 17:15:40 +1200 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2016-08-09 17:20:10 +1200 |
commit | 9fb350dc7c8cc5259ef24e0cb097031179fab1d6 (patch) | |
tree | 839dd0b8ee3f5323b1cd6aefa22b605b99437d62 | |
parent | Mention nosls/sls flags in slsf(1) man page (diff) | |
download | dotfiles-9fb350dc7c8cc5259ef24e0cb097031179fab1d6.tar.gz dotfiles-9fb350dc7c8cc5259ef24e0cb097031179fab1d6.zip |
Improve commenting/exit handling in binscripts
-rwxr-xr-x | bin/cf | 5 | ||||
-rwxr-xr-x | bin/clrd | 5 | ||||
-rwxr-xr-x | bin/d2u | 13 | ||||
-rwxr-xr-x | bin/dub | 21 | ||||
-rwxr-xr-x | bin/fgscr | 5 | ||||
-rwxr-xr-x | bin/gms | 2 | ||||
-rwxr-xr-x | bin/grc | 10 | ||||
-rwxr-xr-x | bin/gscr | 16 | ||||
-rwxr-xr-x | bin/hurl | 8 | ||||
-rwxr-xr-x | bin/igex | 24 | ||||
-rwxr-xr-x | bin/isgr | 9 | ||||
-rwxr-xr-x | bin/jfc | 13 | ||||
-rwxr-xr-x | bin/mkcp | 14 | ||||
-rwxr-xr-x | bin/mkmv | 14 | ||||
-rwxr-xr-x | bin/mktd | 10 | ||||
-rwxr-xr-x | bin/rnda | 14 | ||||
-rwxr-xr-x | bin/rndf | 10 | ||||
-rwxr-xr-x | bin/rndi | 9 | ||||
-rwxr-xr-x | bin/rndl | 26 | ||||
-rwxr-xr-x | bin/rnds | 15 | ||||
-rwxr-xr-x | bin/sls | 8 | ||||
-rwxr-xr-x | bin/slsf | 1 | ||||
-rwxr-xr-x | bin/stbl | 9 | ||||
-rwxr-xr-x | bin/stex | 20 | ||||
-rwxr-xr-x | bin/stws | 9 | ||||
-rwxr-xr-x | bin/sue | 11 | ||||
-rwxr-xr-x | bin/u2d | 13 | ||||
-rwxr-xr-x | bin/urlc | 3 |
28 files changed, 287 insertions, 30 deletions
@@ -1,6 +1,5 @@ #!/bin/sh # Count entries in a given set of directories -ex=0 for dir in "${@:-.}" ; do # Warn if a non-directory was given, flag errors, but continue @@ -25,4 +24,6 @@ for dir in "${@:-.}" ; do # Print number of parameters printf '%u\t%s\n' "$#" "$dir" done -exit "$ex" + +# Exit non-zero if a non-directory was given as an argument +exit "${ex:-0}" @@ -1,5 +1,8 @@ #!/bin/sh +# Clear the screen and read a file as it's written line-by-line self=clrd + +# Check we have an input file and are writing to a terminal if [ "$#" -ne 1 ] ; then printf >&2 '%s: Need input file\n' "$self" exit 2 @@ -7,5 +10,7 @@ elif ! [ -t 1 ] ; then printf >&2 '%s: stdout not a terminal\n' "$self" exit 2 fi + +# Clear the screen and start tailing out the file clear tail -f -- "$@" @@ -1,13 +1,26 @@ #!/bin/sh +# Convert DOS line endings to UNIX ones + +# Check arguments if [ "$#" -eq 0 ] ; then printf >&2 'd2u: Need a filename\n' exit 2 fi + +# Put a carriage return into a variable for convenience r=$(printf '\r') + +# Iterate over arguments and apply the same ed(1) script to each of them for fn ; do + + # Note the heredoc WORD is intentionally unquoted because we want to expand + # $r within it to get a literal carriage return; the escape characters + # prescribed for ed(1) by POSIX are very limited ed -s -- "$fn" <<EOF || ex=1 g/$r\$/ s/$r\$// w EOF done + +# If any of the ed(1) commands failed, we should exit with 1 exit "${ex:-0}" @@ -1,13 +1,32 @@ #!/bin/sh # List the biggest files in a directory -dir=$1 lines=${2:-10} + +# First optional argument is the directory, defaulting to the +# current dir; second optional argument is the number of files to +# show, defaulting to 20 +dir=${1:-.} lines=${2:-10} + +# Enter the target dir or bail cd -- "$dir" || exit + +# Add files matching glob, shift them off if unexpanded (first and +# only entry doesn't exist) set -- * [ -e "$1" ] || shift + +# Add dot files, shift off the "." and ".." entries (sh(1) +# implementations seem to vary on whether they include these) set -- .* "$@" [ -e "$1" ] || shift [ "$1" = . ] && shift [ "$1" = .. ] && shift + +# Run du(1) with POSIX compatible flags -k for kilobyte unit and +# -s for total over the arguments du -ks -- "$@" | + +# Sort the first field (the sizes) numerically, in reverse sort -k1nr | + +# Limit the output to the given number of lines sed "$lines"q @@ -1,4 +1,9 @@ #!/bin/sh # Find all the Git repositories in a directory and scrub them all + +# Check we have gscr(1) first command -v gscr >/dev/null || exit + +# Look for any dir named .git in the given (default current) dir and run +# gscr(1) on it find "${@:-.}" -name '*.git' -type d -exec gscr {} \; @@ -15,7 +15,7 @@ for sig in EXIT HUP INT TERM ; do trap "cleanup $sig" "$sig" done -# Who am I? Don't trust the environment $UID to tell me. +# Don't trust the environment $UID, use id(1) instead uid=$(id -u) || exit # Iterate through the getmailrc.* files in $GETMAIL if defined, or @@ -1,10 +1,16 @@ #!/bin/sh -# Argument or current dir is a Git repository with uncommitted changes +# Check whether a directory is a Git repository with uncommitted changes + +# Enter given directory or bail cd -- "${1:-.}" || exit + +# If not a Git repository at all, warn explicitly if ! isgr ; then printf >&2 'grc: Not a Git repository\n' exit 1 fi -isgr || exit + +# Exit 0 if the first command gives any output (added files) or the second one +# exits 1 (inverted; differences in tracked files) [ -n "$(git ls-files --others --exclude-standard)" ] || ! git diff-index --quiet HEAD @@ -1,6 +1,13 @@ #!/bin/sh -# Scrub a Git repository +# Scrub and pack Git repositories + +# Iterate through given directories; default to the current one for arg in "${@:-.}" ; do ( + + # Note the "exit" calls here in lieu of "continue" are deliberate; we're in + # a subshell, so leaving it will continue the loop. + + # Enter either bare repository or .git subdir case $arg in *.git) cd -- "$arg" || exit @@ -9,7 +16,14 @@ for arg in "${@:-.}" ; do ( cd -- "$arg"/.git || exit ;; esac + + # Check for bad references or other integrity/sanity problems git fsck || exit + + # Expire dangling references git reflog expire --expire=now || exit + + # Remove dangling references git gc --prune=now --aggressive || exit + ) done @@ -1,5 +1,11 @@ #!/bin/sh -# Extract <a href="..."> URLs from an HTML document or documents. +# Extract <a href="..."> URLs from an HTML document or documents + +# Input is either stdin or the given arguments concatenated cat -- "${@:-/dev/stdin}" | # shellcheck disable=SC2002 + +# Pipe through pup to get all the href links pup -p 'a attr{href}' | + +# Sort them uniquely sort | uniq @@ -1,12 +1,34 @@ #!/bin/sh -# Run a command and ignore specified exit values. +# Run a command and ignore specified exit values + +# There should be at least two arguments +if [ "$#" -eq 0 ] ; then + printf >&2 'igs: Need an ignore list x,y,z and a command\n'; +fi + +# The list of values to ignore is the first argument; add a trailing comma for +# ease of parsing; shift it off igs=$1, shift + +# Run the command in the remaining arguments and grab its exit value "$@" ex=$? + +# Iterate through the ignored exit values by chopping its variable and checking +# each value until it's empty while [ -n "$igs" ] ; do + + # Get the first exit value in the remaining list ig=${igs%%,*} + + # If it matches the command's exit value, exit with 0 [ "$((ig == ex))" -eq 1 ] && exit 0 + + # Chop it off the list for the next iteration igs=${igs#*,} done + +# If we got right through the list, we exit with the same value as the command; +# i.e. we are not ignoring the value exit "$ex" @@ -1,8 +1,13 @@ #!/bin/sh # Return an exit status for whether the current directory appears to be in a # Git working copy + +# No output, at all, ever; this is intended for use in scripting exec >/dev/null 2>&1 + +# Enter the given directory (default to current directory) cd -- "${1:-.}" || exit + +# If neither of these commands work, this isn't a Git repository git symbolic-ref --quiet HEAD || -git rev-parse --short HEAD || -exit 1 +git rev-parse --short HEAD @@ -1,7 +1,14 @@ #!/bin/sh -# Commit all changes to a Git repository with a stock message -# message. +# Commit all changes to a Git repository with a stock message message + +# Enter the given directory, default to the current one cd -- "${1:-.}" || exit + +# Check if there are any changes; if not, don't proceed (but it's not an error) grc || exit 0 + +# Add all changes git add --all || exit -git commit --message 'Committed by jfc(1)' --quiet || exit + +# Quietly commit with a stock message and use its exit value as ours +git commit --message 'Committed by jfc(1)' --quiet @@ -1,6 +1,18 @@ #!/bin/sh # Copy files into created directory in one call -[ "$#" -gt 2 ] || exit 2 + +# Check we have at least two arguments +if [ "$#" -lt 2 ] ; then + printf >&2 'mkcp: Need at least one source and destination\n' + exit 2 +fi + +# Get the last argument (the directory to create) for dir ; do : ; done + +# Create it, or bail mkdir -p -- "$dir" || exit + +# Copy all the remaining arguments into the directory (which will be the last +# argument) cp -R -- "$@" @@ -1,6 +1,18 @@ #!/bin/sh # Move files into created directory in one call -[ "$#" -gt 2 ] || exit 2 + +# Check we have at least two arguments +if [ "$#" -lt 2 ] ; then + printf >&2 'mkmv: Need at least one source and destination\n' + exit 2 +fi + +# Get the last argument (the directory to create) for dir ; do : ; done + +# Create it, or bail mkdir -p -- "$dir" || exit + +# Move all the remaining arguments into the directory (which will be the last +# argument) mv -- "$@" @@ -1,6 +1,12 @@ #!/bin/sh # Try to make a random temp directory + +# Get a random seed from rnds(1); if it's empty, that's still workable seed=$(rnds) + +# Build the intended directory name, with the last element a random integer +# from 1..2^31 dn=${TMPDIR:-/tmp}/${1:-mktd}.$$.$(rndi 1 2147483648 "$seed") -mkdir -m 700 -- "$dn" || exit 1 -printf '%s\n' "$dn" + +# Create the directory and print its name if successful +mkdir -m 700 -- "$dn" && printf '%s\n' "$dn" @@ -1,10 +1,20 @@ #!/bin/sh -# Choose a random argument using rndi(1). +# Choose a random argument using rndi(1) + +# Check we have at least one argument if [ "$#" -eq 0 ] ; then printf >&2 'rnda: No args given\n' - exit 1 + exit 2 fi + +# Get a random seed from rnds(1); if it's empty, that's still workable seed=$(rnds) + +# Get a random integet from 1 to the number of arguments argi=$(rndi 1 "$#" "$seed") || exit + +# Shift until that argument is the first argument shift "$((argi-1))" + +# Print it printf '%s\n' "$1" @@ -1,9 +1,17 @@ #!/bin/sh -# Choose a random file from a given directory using rnda(1). Ignores dot files. +# Choose a random file from a given directory using rnda(1); ignores dot files + +# Directory is first argument; defaults to current directory dir=${1:-.} + +# Set the positional parameters to all the non-dotfiles in that directory set -- "$dir"/* + +# Check for an unexpanded glob (empty directory) if ! [ -e "$1" ] ; then printf >&2 'rndf: No files found in %s\n' "$dir" exit 1 fi + +# Print a random argument from the current positional parameters rnda "$@" @@ -2,13 +2,22 @@ # Get a low-quality random number between two integers. Depending on the awk # implementation, if you don't provide a third argument (a seed), you might get # very predictable random numbers based on the current epoch second. + BEGIN { + + # Seed with the third argument if given if (ARGV[3]) { srand(ARGV[3]) } + + # If not, just seed with what is probably a date/time-derived value else { srand() } + + # Print a random integer bounded by the first and second arguments print int(ARGV[1]+rand()*(ARGV[2]-ARGV[1]+1)) + + # Bail before processing any lines exit } @@ -1,6 +1,13 @@ #!/bin/sh # Print a random line from input + +# If there are no arguments, we're checking stdin; this is more complicated +# than checking file arguments because we have to count the lines in order to +# correctly choose a random one, and two passes means we require a temporary +# file if we don't want to read all of the input into memory (!) if [ "$#" -eq 0 ] ; then + + # Try to create the temporary directory with mktd(1) safely td= cleanup() { [ -n "$td" ] && rm -fr -- "$td" @@ -14,10 +21,29 @@ if [ "$#" -eq 0 ] ; then trap "cleanup $sig" "$sig" done td=$(mktd rndl) || exit + + # We'll operate on stdin in the temp directory; write the script's stdin to + # it with cat(1) set -- "$td"/stdin cat >"$td"/stdin fi + +# Count the number of lines in the input lc=$(sed -- '$=;d' "$@") || exit + +# If there were none, bail +case $lc in + ''|0) + printf 2>&1 'rndl: No lines found on input\n' + exit 2 + ;; +esac + +# Try to get a random seed from rnds(1) for rndi(1) seed=$(rnds) + +# Get a random line number from rndi(1) ri=$(rndi 1 "$lc" "$seed") || exit + +# Print the line using sed(1) sed -- "$ri"'!d' "$@" @@ -1,11 +1,22 @@ #!/bin/sh # Try to get a low-quality random seed from a random device if possible -[ "$#" -le 1 ] || exit 2 + +# Sole optional argument is the bytes to read; 32 is the default +count=${1:-32} + +# Try and find a random device to use; none of these are specified by POSIX for dev in /dev/urandom /dev/arandom /dev/random '' ; do [ -e "$dev" ] && break done + +# Bail if we couldn't find a random device [ -n "$dev" ] || exit 1 -count=${1:-32} + +# Read the bytes from the device dd if="$dev" bs=1 count="$count" 2>/dev/null | + +# Run cksum(1) over the read random bytes cksum | + +# cut(1) the cksum(1) output to only the first field, and print that to stdout cut -d' ' -f1 @@ -1,12 +1,20 @@ #!/bin/sh +# Print hostnames from ssh_config(5) files, defaulting to the usual paths + +# If we weren't given a file explicitly, we'll try to read both /etc/ssh_config +# and ~/.ssh_config in that order if they exist if [ "$#" -eq 0 ] ; then for cfg in /etc/ssh_config "$HOME"/.ssh/config ; do [ -e "$cfg" ] || continue set -- "$@" "$cfg" done fi + +# If we still have no files to read, bail out and warn the user if [ "$#" -eq 0 ] ; then printf >&2 'sls: ssh_config(5) paths not found, need argument\n' exit 1 fi + +# Otherwise, we can run slsf(1) over the ones we did collect slsf -- "$@" @@ -1,4 +1,5 @@ #!/usr/bin/awk -f +# Print the first non-glob "Host" name from each line of ssh_config(5) files # Manage the processing flag (starts set in each file) FNR == 1 || /### sls/ { sls = 1 } @@ -1,12 +1,19 @@ #!/bin/sh # Strip a trailing blank line from the given files with ed(1) + +# Check arguments if [ "$#" -eq 0 ] ; then printf 2>&1 'stbl: Need a filename\n' exit 2 fi + +# Iterate over arguments and apply the same ed(1) script to each of them for fn ; do - ed -s -- "$fn" <<'EOF' + ed -s -- "$fn" <<'EOF' || ex=1 $g/^ *$/d w EOF done + +# If any of the ed(1) commands failed, we should exit with 1 +exit "${ex:-0}" @@ -1,15 +1,29 @@ #!/bin/sh -# Strip an extension from the given files +# Strip an extension from the given filenames + +# Check args if [ "$#" -lt 2 ] ; then printf >&2 'Need an extension .ext and a filename\n' exit 2 fi -ex=0 ext=$1 + +# Extension is first arg, shift it off +ext=$1 shift + +# Iterate through the given files (remaining args) for sn ; do + + # Strip trailing slash if any and then extension sn=${sn%/} dn=${sn%"$ext"} + + # Ignore this file if its name wouldn't change [ "$sn" != "$dn" ] || continue + + # Attempt a rename, flag an error if there was one mv -- "$sn" "$dn" || ex=1 done -exit "$ex" + +# Exit with 1 if there was any failed mv(1) run +exit "${ex:-0}" @@ -1,12 +1,19 @@ #!/bin/sh # Strip trailing spaces on one or more files + +# Check arguments if [ "$#" -eq 0 ] ; then printf >&2 'tstf: Need a filename\n' exit 2 fi + +# Iterate over arguments and apply the same ed(1) script to each of them for fn ; do - ed -s -- "$fn" <<'EOF' + ed -s -- "$fn" <<'EOF' || ex=1 g/ *$/ s/ *$// w EOF done + +# If any of the ed(1) commands failed, we should exit with 1 +exit "${ex:-0}" @@ -1,8 +1,17 @@ #!/bin/sh # Run sudoedit(8) with an appropriate user on a set of files + +# Blank out the user variable user= + +# Iterate over the given files for file ; do + + # Get the file's owner, or bail file_owner=$(stat -c %U -- "$file") || exit + + # Check that this file has the same owner as all previously checked files, + # if any case $user in "$file_owner"|'') user=$file_owner @@ -13,4 +22,6 @@ for file ; do ;; esac done + +# Run sudoedit(8) as the user that owns all the files sudoedit -u "$user" -- "$@" @@ -1,14 +1,27 @@ #!/bin/sh +# Convert UNIX line endings to DOS ones + +# Check arguments if [ "$#" -eq 0 ] ; then printf >&2 'u2d: Need a filename\n' exit 2 fi + +# Put a carriage return into a variable for convenience r=$(printf '\r') + +# Iterate over arguments and apply the same ed(1) script to each of them for fn ; do + + # Note the heredoc WORD is intentionally unquoted because we want to expand + # $r within it to get a literal carriage return; the escape characters + # prescribed for ed(1) by POSIX are very limited ed -s -- "$fn" <<EOF || ex=1 g/[^$r]\$/ s/\$/$r/ g/^\$/ s/\$/$r/ w EOF done + +# If any of the ed(1) commands failed, we should exit with 1 exit "${ex:-0}" @@ -25,7 +25,6 @@ list=$td/list head=$td/head body=$td/body # Iterate through input; ignore leading/trailing whitespace # shellcheck disable=SC2002 cat -- "${@:--}" >"$list" -ex=0 while read -r url ; do # Skip anything that doesn't start with HTTP @@ -74,4 +73,4 @@ done <"$list" wait # Exit if any errors -exit "$ex" +exit "${ex:-0}" |