mirror of
https://github.com/lloeki/apply.git
synced 2025-12-06 09:24:38 +01:00
142 lines
4.1 KiB
Bash
Executable file
142 lines
4.1 KiB
Bash
Executable file
# shellcheck shell=dash
|
|
# vim: ft=sh
|
|
|
|
# substitute replaces all occurances of one string with another in the provided
|
|
# file, writing to the specified output file.
|
|
substitute() {
|
|
local input="$1"
|
|
local output="$2"
|
|
|
|
shift 2
|
|
|
|
# TODO: real parsing
|
|
local search="$1"
|
|
local replace="$2"
|
|
|
|
#-v RS="$(printf "\0")" \
|
|
awk \
|
|
-v srch="$search" \
|
|
-v repl="$replace" \
|
|
-v RS="" \
|
|
-v ORS="" \
|
|
'{ gsub(srch, repl, $0); print $0 }' \
|
|
< "$input" > "$output"
|
|
}
|
|
|
|
# substituteInPlace works like substitute but operates in-place on the provided
|
|
# file
|
|
substituteInPlace() {
|
|
local fpath="$1"
|
|
shift
|
|
|
|
local tmpfile
|
|
tmpfile="$(mktemp)"
|
|
|
|
if ! substitute "$fpath" "$tmpfile" "$@"; then
|
|
rm "$tmpfile"
|
|
return $?
|
|
fi
|
|
|
|
# Overwrite now that we've succeeded
|
|
mv "$tmpfile" "$fpath"
|
|
}
|
|
|
|
# Shell-quotes an arbitrary string.
|
|
#
|
|
# From: http://www.etalabs.net/sh_tricks.html
|
|
#
|
|
# This function simply replaces every instance of «'» (single quote) within
|
|
# the string with «'\''» (single quote, backslash, single quote, single
|
|
# quote), then puts single quotes at the beginning and end of the string.
|
|
# Since the only character whose meaning is special within single quotes is
|
|
# the single quote character itself, this is totally safe. Trailing
|
|
# newlines are handled correctly, and the single quote at the end doubles
|
|
# as a safety character to prevent command substitution from clobbering the
|
|
# trailing newlines, should one want to do something like:
|
|
# quoted=$(quote "$var")
|
|
quote() {
|
|
printf "%s\n" "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
|
|
}
|
|
|
|
|
|
# Returns whether or not a string matches a glob; similar to the bash [[ test,
|
|
# but portable.
|
|
fnmatch() {
|
|
# We explicitly want this to act as a glob
|
|
# shellcheck disable=SC2254
|
|
case "$2" in
|
|
$1) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
# Portable equivalent to GNU's `date +"%s"`
|
|
#
|
|
# From: http://www.etalabs.net/sh_tricks.html
|
|
epochseconds() {
|
|
# This is horrible, but... it tells 'date' to generate a string that
|
|
# contains shell math to generate the actual epoch date.
|
|
#
|
|
# TODO(andrew-d): break down and verify the math here
|
|
echo $(( $(TZ=GMT0 date +"((%Y-1600)*365+(%Y-1600)/4-(%Y-1600)/100+(%Y-1600)/400+1%j-1000-135140)*86400+(1%H-100)*3600+(1%M-100)*60+(1%S-100)") ))
|
|
}
|
|
|
|
# user_homedir returns the home directory for the provided user
|
|
user_homedir() {
|
|
local user="$1"
|
|
|
|
awk \
|
|
-v u="$user" \
|
|
-v FS=':' \
|
|
'$1==u {print $6}' \
|
|
/etc/passwd
|
|
}
|
|
|
|
# sponge acts like sponge(1) from moreutils, but is portable.
|
|
#
|
|
# It "soaks up" all input from stdin before writing it to the specified output;
|
|
# helpful for modifying a file in-place with a utility that does not support
|
|
# it.
|
|
sponge() {
|
|
local append=false
|
|
|
|
while getopts 'a' opt; do
|
|
case $opt in
|
|
a) append=true ;;
|
|
*) echo "unknown option: $opt" >&2; exit 1;;
|
|
esac
|
|
done
|
|
shift "$(( OPTIND - 1 ))"
|
|
|
|
local outfile="$1"
|
|
local tmpfile
|
|
|
|
tmpfile="$(mktemp "$(dirname "$outfile")/tmp-sponge.XXXXXXXX")" &&
|
|
cat >"$tmpfile" &&
|
|
if "$append"; then
|
|
cat "$tmpfile" >>"$outfile"
|
|
else
|
|
if [ -f "$outfile" ]; then
|
|
# NOTE: the stat() call here isn't exactly portable, but both GNU
|
|
# coreutils and busybox support it, so close enough? Let's
|
|
# double-check that it returns something sensible just to be sure.
|
|
local oldperms
|
|
oldperms="$(stat -c '%a' "$outfile")"
|
|
|
|
# Should be a string of length 3 with only digits
|
|
if [ "${#oldperms}" = "3" ] && [ -z "$(echo "$oldperms" | tr -d '0-9')" ]; then
|
|
chmod "$oldperms" "$tmpfile"
|
|
else
|
|
printf "warning (bad: %s): not setting permssions on: %s\n" "${oldperms}" "$outfile" >&2
|
|
fi
|
|
fi
|
|
if [ -f "$outfile" ]; then
|
|
mv "$tmpfile" "$outfile"
|
|
elif [ -n "$outfile" ] && [ ! -e "$outfile" ]; then
|
|
cat "$tmpfile" >"$outfile"
|
|
else
|
|
cat "$tmpfile"
|
|
fi
|
|
fi &&
|
|
rm -f "$tmpfile"
|
|
}
|