#!/bin/bash CONFIG_FILE=machines.conf MACHINE_PATTERN=machine=([^@]+@[^:]+\|local):.+ # example 1: machine=username1@pcname1:basedir1 # example 2: machine=local:basedir1 function get_data { old_IFS="$IFS"; IFS="=:@" index=0 for arg in $1; do case $index in 0) ;; # "machine" 1) user=$arg;; # "username1" 2) host=$arg;; # "pcname1" 3) dir=$arg;; # "basedir1" esac let index++ done IFS="$old_IFS" if [ $index -eq 3 ]; then # local dir=$host; unset user host fi if test -n "$user"; then # Remote! tmpfile=.tmpfile.txt scp -q $0 ${user}@${host}:/tmp/ ssh ${user}@${host} chmod a+x /tmp/$0 echo machine=local:${dir} | ssh ${user}@${host} "cat > /tmp/machines.conf" ssh ${user}@${host} "cd /tmp/; /tmp/$0 -r" # Parameter -r ! remote_files=$( ssh ${user}@${host} "cd /tmp/; ls -tr1 *.data *.sums | tail -2" ) ## echo DEBUG remote_files=$remote_files for file in $remote_files; do scp -q ${user}@${host}:/tmp/${file} $tmpfile mv $tmpfile "${user}@${host}:${file}" done return fi filename_prefix="${dir//\//:}" current_dir="$PWD" cd "$dir" find . -type f | cut -c3- > ${current_dir}/${filename_prefix}.files cd "$current_dir"; rm -f ${filename_prefix}.tmpdata while read file; do sum=$( md5sum "$dir/$file" | cut -f1 -d" " ) date=$( stat -c '%y' "$dir/$file" | cut -c1-16 | tr ' :' '-.' ) size=$( stat -c '%s' "$dir/$file" ) # date=$( stat -f "%Sm" "$dir/$file" | tr " " "-" ) # OS X # size=$( stat -f "%z" "$dir/$file" ) # OS X echo "$file!$sum!$date!$size" >> ${filename_prefix}.tmpdata done < ${filename_prefix}.files sort ${filename_prefix}.tmpdata > ${filename_prefix}.data cut -f1,2 -d! < ${filename_prefix}.data > ${filename_prefix}.sums rm ${filename_prefix}.{files,tmpdata} } # Hauptprogramm if [ ! $BASH_VERSION \> 4 ]; then echo "Brauche Bash >= 4.0" exit fi REMOTE_EXEC=$1 # Hier steht bei Remote-Ausfuehrung "-r" drin i=0 while read; do if [[ $REPLY =~ $MACHINE_PATTERN ]]; then machine[$i]="$REPLY"; let i++ fi done < $CONFIG_FILE machines=$i # Daten der verschiedenen Ordner sammeln for ((i=0; i<$machines; i++)); do get_data ${machine[i]} done if [ "$REMOTE_EXEC" = "-r" ]; then exit # Auswertung nur auf lokaler Maschine fi # Daten auswerten for (( i=0; i<$machines; i++)); do echo "pc$i = ${machine[i]}" done echo declare -A hashes dates sizes count # Hash-Datenstrukturen for ((i=0; i<$machines; i++)); do # Eine Datei auslesen datafile=$( echo ${machine[i]} | sed -e s/^machine=// -e s/^local:// -e s/$/.data/ | \ tr "/" ":" ) while read; do line=$REPLY filename=${line%%\!*}; tmp_rest=${line#*\!} hash=${tmp_rest%%\!*}; tmp_rest=${tmp_rest#*\!} date=${tmp_rest%%\!*}; size=${tmp_rest#*\!} if [ "${hashes[$filename]}" = "" ]; then # Datei taucht zum 1. Mal auf ## echo "DEBUG: Erstes Auftreten von $filename in Ordner $i" extra="" num=1 for ((j=0; j<$i; j++)); do extra=$extra"\n"; ((num++)); done hashes[$filename]=$extra$hash dates[$filename]=$extra$date sizes[$filename]=$extra$size count[$filename]=$num else # Datei war schon da hashes[$filename]=${hashes[$filename]}"\n"$hash # append dates[$filename]=${dates[$filename]}"\n"$date # append sizes[$filename]=${sizes[$filename]}"\n"$size # append (( count[$filename]++ )) fi done < $datafile # ggf. Leerzeilen anhängen if [ $i -gt 0 ]; then for filename in "${!hashes[@]}"; do if [ ${count[$filename]} -lt $[i+1] ]; then ## echo DEBUG: i=$i, $filename, count[$filename]=${count[$filename]}, muss verlaengern hashes[$filename]=${hashes[$filename]}"\n" dates[$filename]=${dates[$filename]}"\n" sizes[$filename]=${sizes[$filename]}"\n" (( count[$filename]++ )) fi done fi done # Abweichungen suchen declare -a h d s # Arrays treffer=0 for filename in "${!hashes[@]}"; do # Anzahl der verschiedenen Hash-Eintraege (bei Gleichheit: 1) #echo DEBUG $filename #echo ----START #echo -e ${hashes[$filename]} #echo -e ${sizes[$filename]} #echo -e ${dates[$filename]} #echo ----END num=$( echo -e ${hashes[$filename]} | sed 's/^$/MISSING/' | sort -u | wc -l ) if [ $num \> 1 ]; then ((treffer++)) printf "[%2d] %s:\n" $treffer $filename { for ((i=0; i<$machines; i++)); do echo $treffer; done for ((i=0; i<$machines; i++)); do echo "pc$i:"; done echo -e ${sizes[$filename]} | sed 's/^$//' echo -e ${dates[$filename]} | sed 's/^$/-/' echo -e ${hashes[$filename]} | sed 's/^$/-/' } | pr -5 -t -s" " | xargs printf "[%2d] %s %10s %-17s %s\n" fi done rm *.data *.sums