#!/bin/sh me=$(basename $0) usage() { err=$1; out=2 [ $err -eq 0 ] && out=1 printf "\ $me [OPTION] 'FILTER' FILE... Replace the contents of each FILE after processing with FILTER --backup[=CONTROL] make a backup of each existing destination file -b like --backup but does not accept an argument -C, --compare compare each pair of source and destination files, and in some cases, do not modify the destination at all. -p, --preserve-timestamps apply access/modification times of SOURCE files to corresponding destination files. -S, --suffix=SUFFIX override the usual backup suffix The backup suffix is \`~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX. The version control method may be selected via the --backup option or through the VERSION_CONTROL environment variable. Here are the values: none never make backups (even if --backup is given) numbered make numbered backups existing numbered if numbered backups exist, simple otherwise simple always make simple backups Report "$me" bugs to address@hidden GNU coreutils home page: General help using GNU software: Report "$me" translation bugs to " >&$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 . 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 } if getopt -T >/dev/null 2>&1; test $? -ne 4; then # Enhanced getopt(1) not available and POSIX getopts # only supports short options, so revert to simple manual parsing if test $# -lt 2; then test "$1" = "--help" && usage 0 test "$1" = "--version" && version "$me" usage 1 fi else OPT=$( getopt -o bCpS: \ --long backup::,compare,help,preserve-timestamps,suffix:,version \ -n"$me" -- "$@" || usage 1 ) eval set -- "$OPT" while true; do case "$1" in -b) test "$VERSION_CONTROL" || VERSION_CONTROL="existing" backup="$VERSION_CONTROL"; shift;; --backup) case "$2" in "") backup=existing; shift 2;; *) backup="$2"; shift 2;; esac;; -C|--compare) compare=1; shift;; -p|--preserve-timestamps) preserve_times=1; shift;; -S|--suffix) suffix="$2"; shift 2;; --help) usage 0; shift;; --version) version "$me"; shift;; --) shift; break ;; *) echo "Option processing error"; exit 1;; esac done if test "$backup"; then backup="--backup=$backup" test "$suffix" && backup="$backup --suffix=$suffix" fi if test $# -lt 1; then printf "\ $me: missing file operand Try \`$me --help' for more information. " fi fi filter="$1"; shift cleanup() { rm -f "$tf"; } trap "cleanup" EXIT filter_file() { ret=0 if $filter < "$file" > "$tf"; then if test "$preserve_times"; then touch "$tf" --reference="$file" || { ret=1; fail=1; } fi else ret=1; fail=1 fi if test $ret = 0; then if test "$compare"; then cmp -s -- "$tf" "$file" status=$? test $status -eq 0 && { ret=1; } # Don't process further test $status -gt 1 && { ret=1; fail=1; } fi fi return $ret } 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 && { mv $backup -- "$tf" "$file" || fail=1; } # rename else # 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. cleanup # dir/file.tmp tf=$(mktemp) filter_file && { cp $backup -- "$tf" "$file" || fail=1; } # truncate and copy test "$preserve_times" && touch "$file" --reference="$tf" cleanup # tmp/file.tmp fi done exit $fail