tardiff 1.42 KB
#!/bin/bash

##
# Create an unified diff over two tar archives.
#
# Author: Georg Hopp <ghopp@bigpoint.net>
# Date: Tue Apr 17 17:19:56 CEST 2012
# Version: 1.0.0
#

##
# This one is not POSIX conform. POSIX does not define
# process substitution via <() or >(). The alternative
# I tries is using fifos but doing this with seems to
# be a synchonization nightmare.
#

function tardiff() {
	local SED="/bin/sed"
	local SORT="/usr/bin/sort"
	local TAR="/bin/tar"
	local DIFF="/usr/bin/diff"
	local XARGS="/usr/bin/xargs"
	local BASH="/bin/bash"

	if [ 2 -ne $# ]
	then
		echo "tardiff tar1 tar2"
		return 1
	fi

	local TAR1=$1
	local TAR2=$2

	local FILES1="${TAR} tfa \"${TAR1}\""
	local FILES2="${TAR} tfa \"${TAR2}\""

	##
	# get the union of all files in both tar's
	# Exclude directories.
	#
	local FILES="${SORT} -u <(${FILES1}) <(${FILES2}) | ${SED} '/\/$/d'"

	##
	# create a diff over all files and change the /dev/fd/ entries
	# with the current filename.
	# The resulting diff can be used as a patch on the extracted
	# first tar to get the content of the extracted second tar.
	#
	eval ${FILES} | ${XARGS} -I %file ${BASH} -c "
		FILE=\"%file\"
		ESC_FILE=\"\${FILE//\//\/}\"
		${DIFF} -Nau \
		<(${TAR} xfOa \"${TAR1}\" \"%file\" 2>/dev/null) \
		<(${TAR} xfOa \"${TAR2}\" \"%file\" 2>/dev/null) | \
		${SED} 's/\/dev\/fd\/[0-9]\+/'\${ESC_FILE}'/'"
}

test "X$(basename -- "$0")" = "Xtardiff" && tardiff "$@"

# vim: set ft=sh ts=4 sw=4: