blob: a9cd115e4f791e85039147359b140ae91fd29884 (
plain) (
tree)
|
|
#
# 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 IFS= 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[@]}" "$@"
}
|