aboutsummaryrefslogtreecommitdiff
path: root/bash
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2015-07-23 14:38:04 +1200
committerTom Ryder <tom@sanctum.geek.nz>2015-07-23 14:38:04 +1200
commit3ea08b5fb4e2062b14772ffea3476470c246907f (patch)
treebff2272bf79dbf73736600424144565ca61046cd /bash
parentRemove a few unneeded quotes (diff)
downloaddotfiles-3ea08b5fb4e2062b14772ffea3476470c246907f.tar.gz
dotfiles-3ea08b5fb4e2062b14772ffea3476470c246907f.zip
Add apf func (argument prepend [from] file)
Diffstat (limited to 'bash')
-rw-r--r--bash/bashrc.d/apf.bash100
1 files changed, 100 insertions, 0 deletions
diff --git a/bash/bashrc.d/apf.bash b/bash/bashrc.d/apf.bash
new file mode 100644
index 00000000..af759577
--- /dev/null
+++ b/bash/bashrc.d/apf.bash
@@ -0,0 +1,100 @@
+#
+# apf -- arg-prepend-file -- Prepend null-delimited arguments read from a file
+# to a command's arguments before running it. This is intended as a way of
+# implementing *rc files for interactive Bash calls to programs that don't
+# support such files, without having to use broken environment variables (e.g.
+# GREP_OPTIONS); this enables you to, for example, use arguments with shell
+# metacharacters and spaces in them that you do not want expanded.
+#
+# For example, given this simple program in our $PATH, printargs:
+#
+# $ cat ~/.local/bin/printargs
+# #!/bin/sh
+# printf '%s\n' "$@"
+#
+# Which just prints its arguments:
+#
+# $ printargs a b c
+# a
+# b
+# c
+#
+# We could do this:
+#
+# $ printf '%s\0' -f --flag --option '? foo bar *' > "$HOME"/.printargsrc
+#
+# $ apf "$HOME"/.printargsrc printargs a b c
+# -f
+# --flag
+# --option
+# ? foo bar *
+# a
+# b
+# c
+#
+# We could then make a permanent wrapper function with:
+#
+# $ printargs() { apf "$HOME"/.printargsrc printargs "$@" ; }
+#
+# $ printargs a b c
+# -f
+# --flag
+# --option
+# ? foo bar *
+# a
+# b
+# c
+#
+# $ printf '%s\n' !-2:q >> "$HOME"/.bashrc
+#
+# This means you can edit the options in the *rc file and don't have to
+# redefine a wrapper function.
+#
+# If you actually want those options to *always* be added, regardless of
+# whether you're in an interactive shell, you really should make an actual
+# wrapper script.
+#
+apf() {
+
+ # Require at least two arguments, give usage otherwise
+ if (($# < 2)) ; then
+ printf 'bash: %s: usage: %s ARGFILE COMMAND [ARGS...]\n' \
+ "$FUNCNAME" "$FUNCNAME" >&2
+ return 2
+ fi
+
+ # First argument is the file containing the null-delimited arguments
+ local argfile=$1
+ shift
+
+ # Check the arguments file makes sense
+ if [[ ! -e $argfile ]] ; then
+ printf 'bash: %s: %s: No such file or directory\n' \
+ "$FUNCNAME" "$argfile"
+ return 1
+ elif [[ -d $argfile ]] ; then
+ printf 'bash: %s: %s: Is a directory\n' \
+ "$FUNCNAME" "$argfile"
+ return 1
+ elif [[ ! -r $argfile ]] ; then
+ printf 'bash: %s: %s: Permission denied\n' \
+ "$FUNCNAME" "$argfile"
+ return 1
+ fi
+
+ # Read all the null-delimited arguments from the file
+ local -a args
+ local arg
+ while read -d '' -r arg ; do
+ args=("${args[@]}" "$arg")
+ done < "$argfile"
+
+ # Next argument is the command to run
+ local cmd=$1
+ shift
+
+ # Run the command with the retrieved arguments first, then the rest of the
+ # command line as passed to the function
+ command "$cmd" "${args[@]}" "$@"
+}
+