From: | Sven Utcke |
Date: | 21 Oct 1994 |
Barry Schwartz writes: The cpif program addresses this problem.
This is now the second time that I hear about cpif. What is it? Can it be used with, say, FWEB (the literate program of my choice)? If so, where can I get it (ask archie, I suppose?)?
From: | Joachim Schrod |
Date: | 21 Oct 1994 |
cpif is part of the noweb distribution, it copies standard input to a file only if the contents did not change. (Or did change, as you want.)
#!/bin/sh # cpif [ -eq -ne ] file... # copy standard input to each of the named files # if new * old is true or old doesn't exist; # * defaults to -ne PATH=/bin:/usr/bin # set -x op=-ne case "$1" in -eq|-ne) op=$1; shift ;; -*) echo 'Usage: '`basename $0`' [ -eq -ne ] file...' 1>&2; exit 2 esac case $# in 0) echo 'Usage: '`basename $0`' [ -eq -ne ] file...' 1>&2; exit 2 esac new=/tmp/$$ trap 'rm -f $new; exit 1' 1 2 15 # clean up files cat >$new for i do cmp -s $new $i case $op$? in -eq0|-ne1|*2) cp $new $i esac done rm -f $newActually, not long ago I needed to extend this to `real' file copy operations, so here is my copyif. (E.g., I use it for parser generators like PCCTS who create the scanner as an intermediate file and would trigger spurious compilation of the scanner as it has changed.) As it's roughly upward compatible (as long as only one file is `cpif'ed), I use it for noweb, too...
# # copyif -- copy files if comparison succeeds # # (history at end) # SYNOPSIS # # copyif [-eq | -ne] file # copyif [-eq | -ne] file1 file2 # copyif [-eq | -ne] file ... dir # # # copyif copies a file if a comparison succeeds or if the target file # does not exist. The comparison is either a test if the contents is # equal (-eq) or if it has changed (-ne). The default is -ne. # # The first call form copies standard input to <file>file</>. The second # one copies <file>file1</> to <file>file2</>. The third copies all # <file>files</>s into directory <file>dir</>. # # The source file(s) and also the target file/dir must be readable, # and target must be writable. # # A typical usage is in Makefiles where a file shall only be copied if # it has changed. # # cmd=`basename $0` usage() { cat <<_EOF_ >&2 usage: $cmd: [-eq | -ne] file $cmd: [-eq | -ne] file1 file2 $cmd: [-eq | -ne] file ... dir _EOF_ exit $1 } # parse options... test $# = 0 -o "$1" = '-?' && usage 1 # default is -ne case "$1" in -ne|-eq) test=$1 shift ;; *) test='-ne' ;; esac # one parameter => save source from stdin in $tmp_file if [ $# = 1 ] then tmp_file=/tmp/copyif$$ trap "rm -f $tmp_file" 0 1 2 3 15 cat >$tmp_file src=$tmp_file dest_file=$1 dest_dir='' fi # two parameter if [ $# = 2 ] then src=$1 # Target argument might be a directory, ie, this might be a # call of form 3. if [ -d "$2" ] then dest_file='' dest_dir=$2 else dest_file=$2 dest_dir='' fi fi # n parameter # $1 .. $n-1 are $src # $n is $dest_dir if [ $# -gt 2 ] then # Split list of arguments on last blank and assign thereby the # source files to $src. src=`expr "$*" : '\(.*\) '` dest_file='' # Discard all source arguments shift `expr $# - 1` # Check if target argument is a directory, complain if not if [ ! -d "$1" ] then echo "$cmd: $1: not a directory." >&2 usage 2 else dest_dir=$1 fi fi # pre: # $src is list of source files # either $dest_dir is destination directory # or $dest_dir is empty and $dest_file is destination file and # $src is only one file result_code=0 for file in $src do test "$dest_dir" && dest_file=$dest_dir/$file # now $dest_file holds the target file name # check if it exists if [ -f $dest_file ] then cmp $file $dest_file >/dev/null result="$test$?" case "$result" in *2) # error in cmp command, message was issued exit 2 ;; -eq1|-ne0) continue ;; esac fi cp $file $dest_file result_code=`expr $result_code + $?` done # If there was at least one error in cp, add 10 to the result code. # This way we get a unique exit code that we can distinguish from # internal errors. test $result_code != 0 && result_code=`expr $result_code + 10` exit $result_code
From: | Lee Wittenberg |
Date: | 24 Oct 1994 |
cpif is a tool that comes with the noweb distribution. It's designed to work with makefiles, and should work with any system. You can find it in the noweb distribution in the CTAN archives (under the shell directory; the man page cpif.1 is in the xdoc directory). Cpif is a shell script, but Barry Schwartz has ported it to DOS, but this version hasn't been officially released yet, because Lee Wittenberg has been to d--- lazy to build a new DOS noweb distribution with it enclosed.