On 22/03/10 03:26, Pádraig Brady wrote:
> Right. So the logic would be something like:
Here is a tested `replace` script which is backwards
compatible (non atomically) with older coreutils.
#!/bin/sh
me=$(basename $0)
usage() {
err=$1; out=2
[ $err -eq 0 ] && out=1
echo "$me 'filter' FILE..." >&$out
exit $err
}
version() {
Cmd=$1; Date=2010; Version=8.5 #TODO: auto update
#TODO: translation
printf "\
$Cmd (GNU coreutils) $Version
Copyright (C) $Date Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Pádraig Brady.
"
exit 0
}
# TODO: perhaps support the --compare like `install`
# so as to not cp/mv if ! cmp -s -- "$tf" "$file"
if test "$#" -lt 2; then
test "$1" = "--help" && usage 0
test "$1" = "--version" && version $me
usage 1
fi
filter="$1"; shift
cleanup() { rm -f "$tf"; }
trap "cleanup" EXIT
fail=0
for file in "$@"; do
dir=$(dirname -- "$file")
tf=$(mktemp -q --tmpdir="$dir")
if test -e "$tf" && cp --attr -- "$file" "$tf" 2>/dev/null; then
# Modify file atomically.
# We could `chmod u+rw` here to allow updating non rw files?
$filter < "$file" > "$tf" &&
{ mv -- "$tf" "$file" || fail=1; } # rename
else
cleanup
tf=$(mktemp)
# cp doesn't support --attributes-only or
# $dir is not writeable. In this case we
# use $TMPDIR, but don't use mv to unlink/copy
# as $TMPDIR might not support all attrs of $dir.
# Also we can't unlink in unwriteable dir.
# Note we won't be able to update non rw files like this.
$filter < "$file" > "$tf" &&
{ cp -- "$tf" "$file" || fail=1; } # truncate and copy
fi
done
exit $fail