高度なファイルフィルタリング

高度なファイルフィルタリング

履歴、受信トレイ、バックアップという3つのフォルダがあります。

バックアップに存在しないすべてのファイルを履歴から受信トレイにコピーする必要があります。

どうすればいいですか?

答え1

たとえば、履歴にサブフォルダがありますか?

for x in history/*;
do
  [[ -f backup/"$(basename "$x")" ]] || cp "$x" inbox
done

このスクリプトは、履歴フォルダー内のすべての可能なファイルを繰り返し、そのデフォルト名(例:/ bin / lsのデフォルト名はls)を抽出し、ファイルがバックアップフォルダーにあることを確認し、そうでない場合はプログラムのコピーを実行します。 。 。

答え2

この単純なスクリプトは、3つのディレクトリにサブディレクトリが含まれていない場合にのみ機能します(この場合を処理するにはより複雑な再帰アルゴリズムが必要です)。

Warlockの答えは優れていますが、Warlockの1行スクリプトと比較してこのようなスクリプトの利点は、xargsを使用してコピーされたすべてのファイルに対してcpインスタンスを生成しないことです。 xargsがシェルのコマンドライン長制限を満たすコマンドラインを生成するたびに、cpインスタンスのみがフォークされます。これは、最新のシステムでは大きな傾向があるため、歴史的に何百または数千のファイルがあっても、cp Totalインスタンスを1つだけ実行する可能性が高くなります。

#! /bin/sh

# use tempfile(1) if available, otherwise use:
# EXCLUDEFILE="/tmp/excl.$$"
EXCLUDEFILE=$(tempfile -p excl)

# generate an exclude file, changing backup/ to history/    
find  backup/ -type f | sed -e 's:^backup/:history/:' > "$EXCLUDEFILE"

find history/ -type f -print0 | \
  grep -z -Z -F -v -x -f "$EXCLUDEFILE" | \
  xargs -0r -i{} cp {} inbox/

rm "$EXCLUDEFILE"

ちなみに、ここで使用されるgrepオプションの長い形式は次のとおりです。

grep --null-data --null --fixed-strings --invert-match \
      --line-regexp --file "$EXCLUDEFILE"

より簡潔な形式は次のとおりです。

grep -zZFvxf "$EXCLUDEFILE"

ほとんどのオプションは一般的に使用されるか、説明は必要ありませんが、そのうちの3つは説明が必要な場合があります。

-z--null-datagrepにnullで終わる入力(でfind -print0)を期待するように指示するか、grepにnullで終わる行(にパイプされている)を出力するように指示するか、grepに全体の行全体を一致させるように指示します
-Z--nullxargs -0
-x--line-regexp

関連情報