次のファイルがあるとしましょう。
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
使用して0
NULで区切られたリストを分割します。
new_files=(
${(0)"$(
rsync --out-format=%f -rcn new/ old/ |
perl -p -l0 -e 's/\\#([0-7]{3})/chr(oct($1))/ge'
)"}
)