Show sha1_cache.sh syntax highlighted
#! /bin/sh
#
# $Id: sha1_cache.sh 13096 2007-03-15 17:12:47Z cbiere $
#
# Requires:
#
# bitter - see http://www.ghostwhitecrab.com/bitter/
# stat - The stat tool provided by FreeBSD, NetBSD or GNU coreutils.
#
# Purpose:
#
# Create a list of files and their SHA1 sums, filesizes and
# modification times. This list can be used with gtk-gnutella.
# Just copy or append it to ~/.gtk-gnutella/sha1_cache but
# make sure gtk-gnutella is not running at the same time. This
# is especially useful if you want to add a large amount of
# files to your shared collection. gtk-gnutella has to throttle
# SHA-1 calculation to prevent long stalls. Thus, this script
# will be faster and you can off-load the calculation to a
# different machine or use it when gtk-gnutella is not running.
#
# Example:
#
# Let's assume you want to share *all* files under /my_shared_files:
#
# $ cd /my_shared_files
# $ find . -type f -print0 | xargs -0 sha1_cache.sh > ~/tmp/filelist
#
# Terminate gtk-gnutella if it's currently running
#
# $ cat ~/tmp/filelist >> ~/.gtk-gnutella/sha1_cache
#
# Restart gtk-gnutella and add "/my_shared_files" to your shared
# directories under "Preferences->Uploads" and click on "Rescan".
# The blue SHA-1 icon should not show up since all SHA-1 hashes
# are already known.
#
# Caveats:
#
# Filenames should not contain any control characters especially
# not newline characters '\n'. Normal whitespace character are
# fine.
#
if [ $# -lt 1 ]; then
echo 'sha1_cache.sh FILE_1 ... FILE_n' >&2
exit 1
fi
# Detect the variant of "stat"; unfortunately there is no standard
# for this. It is needed to get the filesize and timestamp of a file.
stat=$(stat --version 2>/dev/null | sed -n 's,^.*\(coreutils\).*$,\1,p')
stat /dev/null >/dev/null 2>&1 || {
echo 'ERROR: The stat tool seems unusable.' >&2
exit 1
}
# Current working directory; for converting relative pathnames
path=$(pwd) || exit
case "${path}" in
/*)
;;
*) echo 'ERROR: Could not detect absolute path.' >&2
exit 1
;;
esac
while [ $# -gt 0 ]; do
file=$1
shift
# Convert relative pathnames to absolute pathnames.
case "${file}" in
/*)
;;
*) file="${path}/${file}"
;;
esac
# Normalize the filename by removing unnecessary "/." and "//" sub strings.
file_norm=${file}
while :; do
file=${file_norm}
file_norm=$(printf '%s' "${file_norm}" | sed 's,/[./]/,/,g; s,//,/,g')
if [ "${file}" = "${file_norm}" ]; then
break
fi
done
# Transform "/foo/../" into "/"
file_norm=${file}
while :; do
file=${file_norm}
file_norm=$( printf '%s' "${file_norm}" | sed 's,/[^/]*/[.][.]/,/,')
echo "${file_norm}" >&2
if [ "${file}" = "${file_norm}" ]; then
break
fi
done
if [ ! -f "${file}" ]; then
printf 'Not a regular file: "%s"\n' "${file}" >&2
continue
fi
sha1=$(bitter -S < "${file}") || continue
sha1=$(printf '%s' "${sha1}" | sed 's,^urn:sha1:,,') || continue
if [ "${stat}" = 'coreutils' ]; then
size=$(stat -c '%s' -- "${file}") || continue
stamp=$(stat -c '%Y' -- "${file}") || continue
else
size=$(stat -f '%z' -- "${file}") || continue
stamp=$(stat -f '%m' -- "${file}") || continue
fi
printf '%s\t%s\t%s\t%s\n' "${sha1}" "${size}" "${stamp}" "${file}" || break
done
exit
See more files for this project here