
大きなタールがあり、定期的にその内容を固定位置に抽出するとしましょう。
私は、この場所を抽出されたtarの元のインスタンスとして維持したいと思っており、tarに存在する可能性がある小さな変更を更新するために、常に出力ディレクトリを消去する非常に無駄なプロセスを回避できます--keep-newer-files
。
しかし、アーカイブに存在しなくなったファイルを出力場所からどのように削除しますか?
答え1
標準tar
コマンドには、アーカイブの内容をリストする方法があります。その略語はですtar -tf archive.tar
。
find
、およびコマンド置換と組み合わせて使用すると、grep
次の結果が得られます。
rm -f $(find . -d | head -n -1 | grep -Fv "$(tar -tf archive.tar)")
これを実行存在するコンテンツをアーカイブするディレクトリで、アーカイブファイルarchive.tar
のパスに置き換えられます。
最も外側のコマンド置換の内側にあるパイプの場合は、右から左に作業します。
find . -d
:現在のディレクトリ内のすべてのファイルとディレクトリを深さ優先順に一覧表示します。ここでは、このファイルのリストを削除に使用する予定なので、深さ優先ソートが重要であるため、ディレクトリ自体を削除する前にディレクトリの内容を削除する必要があります。head -n -1
:コマンドから最後の行を除外しますfind
。これにより、/path
アーカイブに存在するか存在しない可能性がある項目自体が削除されます。奥行き優先順に操作を実行しないと、これになりますtail -n -1
。grep -Fv "$(tar -tf archive.tar)"
:アーカイブリストをgrepコマンドに渡すと、返されたリストからその行がフィルタリングされるため、find
アーカイブにないファイルのみが外部rm
コマンドに渡されます。
いくつかの注意:
- これではないかもしれません。かなりPOSIX規格に準拠しています。しかし、GNU bashでは動作します。
- これは、tarがアーカイブの内容を報告する方法と、アーカイブの作成方法によって異なります。特に、リストは
find
報告方法と一致する必要があります。 GNU tarとほとんどのアーカイブの場合しなければならない働くあなたの場合に動作しない場合は、最も内側のコマンド置換内またはtarコマンドの出力を使用してsed
動作させることができます。awk
- 本番データで使用する前に確認してテストしてください。上記の2つの理由のいずれかが原因で機能しない場合は、削除することができます。すべて実行するディレクトリを作成します。
答え2
ctime
抽出されたファイルがアーカイブ抽出を開始した時間より後であることを信頼できます。
だから:
touch start
tar xf archive.tgz
find . -depth ! -cnewer start -print0 |
sponge /dev/stdout |
xargs -r0 echo rm -d
(これは、完全なリストが収集されるまで削除を遅らせるために使用されるGNUツールまたは互換性とsponge
fromを想定します。そうしないと、ファイルを削除すると親ディレクトリのctimeが更新されます。)moreutils
実際にこれを行うには、削除しますecho
(必要な操作を実行していることを確認した後)。
答え3
grep -v
アーカイブが少し大きく、コマンドが通過したため、このトリックは私には機能しませんでした。パラメータリストが長すぎます。。 MediaWikiのインストールに積み重ねられたジャンクを取り除くために私が使用する方法は次のとおりです。
$ tar -tzf mediawiki-1.35.0.tar.gz | cut -d/ -f2- > foo
$ find /var/www/mediawiki/ | cut -d/ -f5- | while read f;
do grep -qw "^${f}$" foo || echo "not in archive: ${f}"; done
-f
正しい結果を得るには、パラメータを少し調整する必要がありますが、cut
ここでのコマンドはそうではありません。削除する何でも印刷されます。いいえ私たちのアーカイブに含まれています。