February 2001
The Shell Corner: cmptree
Convert Revisited
Last month, Gerard van Wageningen submitted convert, a Korn script to display numbers in binary, decimal, hexadecimal, and base 36. After my deadline, Gerard submitted a change, adding base 64. If anyone desires this change, please email me and I'll send it to you.
Directory Comparison with cmptree
This month, Ives Aerts submits cmptree
, a bash script that compares the contents of two directories and reports if like-named files are different. It also reports a missing file or directory as not existing. Simply execute:
cmptree directory1 directory2</Pre> Comparing directories is not new. SCO Unix has provided shell script <code>dircmp</code> since before System V, and Solaris also provides a version of <code>dircmp</code>. For Unix variants that dont have a directory compare, such as RedHat Linux 6.1, <code>cmptree</code> is a worthy addition.</P> While <code>dircmp</code> executes a <code>find</code> on each directory comparing contents, <code>cmptree</code> elegantly compares the two directories recursively. The simplicity of <code>cmptree</code> eliminates some of the functionality of <code>dircmp</code>.</P> <B> <h3><code>cmptree</code> Limitations</h3> </B> <code>cmptree</code> reports only if files are different -- not what the differences are.</P> <code>cmptree</code> only compares normal files. Special files, such as block, character, named pipe, semaphore, and shared memory are marked as "unknown."</P> Also, <code>cmptree</code> uses <code>test -e</code> to check whether an object exists; thus, no read permissions causes an "object does not exist" error.</P> Soft links report only if they are different. For example, two directories exist: <code>/tmp/dir1</code> and <code>/tmp/dir2</code>. In the present working directory, create two soft links:</P> <Pre>ln -s /tmp/dir1 linkdir1 ln -s /tmp/dir2 linkdir2Executing the following:
cmptree /tmp/dir1 /tmp/dir2performs a valid search, but executing:
cmptree linkdir1 linkdir2displays a "different link targets" message.
Bash Versus Korn Shell
cmptree
is a bash shell script, but removing the function keyword in each function allows Korn shell execution.
In Ives' original submission, cmptree
's comparefile
function performed compares with:
cmp $1 $2
While the command above works fine in the bash shell, in the Korn, the file name does not list. I changed the cmp
command to return an exit code, sampling the value as such:
cmp -s $1 $2 if [ $? -gt 0 ]; then echo "$1 different from $2" fiThe code snippet above works in both the bash and Korn shells.
#!/bin/bash # # cmptree: compare directory trees recursively and report the differences. # Author: Ives Aerts function gettype () { if [ -L $1 ]; then echo "softlink" elif [ -f $1 ]; then echo "file" elif [ -d $1 ]; then echo "directory" else echo "unknown" fi } function exists () { if [ -e $1 -o -L $1 ]; then return 0; else echo "$1 does not exist." return 1; fi } function comparefile () { cmp -s $1 $2 if [ $? -gt 0 ]; then echo "$1 different from $2" # else # echo "$1 same as $2" fi return } function comparedirectory () { local result=0 for i in `(ls -A $1 && ls -A $2) | sort | uniq`; do compare $1/$i $2/$i || result=1 done return $result } function comparesoftlink () { local dest1=`ls -l $1 | awk '{ print $11 }'` local dest2=`ls -l $2 | awk '{ print $11 }'` if [ $dest1 = $dest2 ]; then return 0 else echo "different link targets $1 -> $dest1, $2 -> $dest2" return 1 fi } # compare a file, directory, or softlink function compare () { (exists $1 && exists $2) || return 1; local type1=$(gettype $1) local type2=$(gettype $2) if [ $type1 = $type2 ]; then case $type1 in file) comparefile $1 $2 ;; directory) comparedirectory $1 $2 ;; softlink) comparesoftlink $1 $2 ;; *) echo "$1 of unknown type" false ;; esac else echo "type mismatch: $type1 ($1) and $type2 ($2)." false fi return } if [ 2 -ne $# ]; then cat << EOU Usage: $0 dir1 dir2 Compare directory trees: files are binary compared (cmp) directories are checked for identical content soft links are checked for identical targets EOU exit 10 fi compare $1 $2 exit $?
Check out past winners of shell corner!!!
By day, Ed Schaefer is a mild-mannered senior programmer-analyst for Intel's Factory Integrated Information Systems (FIIS). The standard employer-employee disclaimer is in effect: In this forum, Ed doesn't speak for Intel and his views on Unix and all other topics are his own.