リモートホストとdiffる
bashの「Process Substitution」という機能で、コマンドの実行結果を名前つきパイプから読めます。(thx かつみくん)
$ cat -n <(date; echo foo) 1 Wed Jan 18 21:38:30 JST 2006 2 foo
これを使って、リモートホストのファイルとdiffを取るシェル関数を作ってみました。
こんな感じで使えます。
$ rdiff -u ~/s.txt REMOTE_HOST:~/d.txt
また-Rオプションで、rsyncの-R, --relativeオプションの様にローカルホストのパスをリモートホストの相対パスとして指定できます。たとえば、ローカルホストの/very/very/long/path/t.txtとリモートホストの同じパスのファイルをdiffるときには次のようにしてリモートホスト側のパス指定を略記することができます。
$ rdiff -uR /very/very/long/path/t.txt REMOTE_HOST:/
ローカルマシンとサーバ上のファイルの比較や、同じ構成のサーバがたくさんあるときのファイル比較に使うとすごぉく便利です。
rdiff() { diff_orig=$(which diff 2>/dev/null) if [ -z "$diff_orig" ]; then echo "cannot find diff command." 1>&2 return 1 fi declare -a opts declare -a files optv=("$@") optc=${#optv[@]} files=(${optv[$optc-2]} ${optv[$optc-1]}) unset optv[$optc-1] unset optv[$optc-2] file_relative= i=0 for o in "${optv[@]}"; do case "$o" in *R*) optv[$i]=$(echo $o | sed -e 's/\-\?R//g') files[0]=$(readlink -f ${files[0]}) file_relative=${files[0]} ;; esac i=$(($i+1)) done optv=(${optv[@]}) case "${files[@]}" in *:*) for i in 0 1; do case ${files[$i]} in *:*) eval $(echo ${files[$i]} | awk -F':' '{printf "t_host=%s t_file1=%s", $1, $2}') if [ -n "$file_relative" ]; then t_file1="$file_relative" fi files[$i]=<(ssh $t_host cat $t_file1) ;; *) ;; esac done ;; *) ;; esac $diff_orig "${optv[@]}" "${files[@]}" }