diff:2番目のディレクトリで別のファイルを探す

diff:2番目のディレクトリで別のファイルを探す

次のファイルがあるとしましょう。

old/common-change/index.html
new/common-change/index.html
new/only-new/index.html
old/only-old/index.html

出力はdiff -qr私が望むものに近いです。

$ diff -qr old/ new/
Files old/common-change/index.html and new/common-change/index.html differ
Only in new/: only-new
Only in old/: only-old

ただし、ファイルのみにはnew/ファイル名が必要です。親ディレクトリだけではありません。を試しましたが、diff -qrN内の項目だけを簡単にフィルタリングすることはできませんold/

$ diff -qrN old/ new/
Files old/common-change/index.html and new/common-change/index.html differ
Files old/only-new/index.html and new/only-new/index.html differ
Files old/only-old/index.html and new/only-old/index.html differ

に含まれていますが、他のものを探したいので、に含まれているものだけをnew/削除したいと思いますold/

diff出力を取得する唯一のファイルは次のとおりです。

new/common-change/index.html
new/only-new/index.html

重要な場合は、最後のコミット以降にWebサイトリポジトリのどのページが変更されたかを知りたいと思います。以前のバージョンをにold/、現在のバージョンをにビルドしていますnew/。したがって、変更されたすべてのページでテストを実行したいのですが、削除されたページは無視したいです(存在しないページではテストを実行できないため)。

答え1

を使用すると、zsh次のことができます。

zmodload zsh/stat
old=(old/**/*(ND-.)); old=(${old#old/})
new=(new/**/*(ND-.)); new=(${new#new/})

# in new, not in old:
new_files=(${new:|old})

# loop over files common to both sets:
for file (${old:*new}) {
  stat -A old_size +size -- old/$file || continue
  stat -A new_size +size -- new/$file || continue
  # compare size to avoid calling cmp as an optimisation
  (( old_size == new_size )) ||
    cmp -s -- {old,new}/$file ||
    new_files+=($file)
}

結果をに入れ、$new_files同様の方法を使用して各項目にls -ld -- new/$^new_filesリストを渡します。new/ls

答え2

おそらく最善の解決策ではないかもしれませんが、一連のパイプを使用して何かを見つけました。

diff -qrN old/ new/ |
    grep -oP '(?<=\s)new\/\S*' |
    xargs -rd '\n' ls -1d 2>/dev/null

これを行うより良い方法があるかどうか疑問に思います。

答え3

1つのオプションは、これをdry-run + checksumモードで使用することですrsync。ここでは、結果を bash 4.4+ 配列に格納し、rsync を使用してシーケンスをperlデコードして、一部のバイト値をエンコードします。\#ooo

readarray -td '' new_files < <(
    rsync --out-format=%f -rcn new/ old/ |
      perl -p -l0 -e 's/\\#([0-7]{3})/chr(oct($1))/ge'
  )

のように、パラメータ拡張フラグをzsh使用して0NULで区切られたリストを分割します。

new_files=(
  ${(0)"$(
    rsync --out-format=%f -rcn new/ old/ |
      perl -p -l0 -e 's/\\#([0-7]{3})/chr(oct($1))/ge'
  )"}
)

関連情報