複数のディレクトリにある複数のファイルの最新バージョンを探す

複数のディレクトリにある複数のファイルの最新バージョンを探す

私はアプリケーションを作成しており、前提条件の1つは、複数のディレクトリを調べて各ファイルの最新バージョンを見つけることができることです。

最新のファイルを正常に使用してインポートlsしたが、同じファイルが複数のディレクトリにある場合は、各ファイルの最新バージョンではありません。find注目すべき点の1つは、ファイル名は必ずしもわかりませんが、ディレクトリ名はわかっていることです。

例:DIR1、DIR2、DIR3 にはそれぞれ FileA バージョンと FileB バージョンが含まれています。 3つ以上のディレクトリに含まれる最新バージョンのFileAとFileBが必要です。

誰にもアイデアがありますか?

答え1

正しいツールを選択しました。

  • ls -tファイルを時間別にソートして最新のファイルを選択するのに最適な方法です。
  • findディレクトリとサブディレクトリで特定のパターンに一致するファイルを見つけるのに適したツールです。

もちろん、トリッキーな部分は、ファイル名ごとに一種のグループ化が必要で、各グループから最新のファイルを選択する必要があるということです。これらの要件のために、最新バージョンを見つけるために各ターゲットファイル名を繰り返すループが必要だと思います。

ファイルがまたはにあると仮定すると、$dir1$dir2のよう$dir3にいくつかのスキーマの最新バージョンを見つける関数を作成できます。

find_latest() {
    pattern=$1
    ls -t "$dir1/$pattern" "$dir2/$pattern" "$dir3/$pattern" | head -n 1
}

その後、パターンがあると仮定すると、access.log次のように繰り返すことができます。error.logx*

for pattern in access.log error.log 'x*'; do
    latest=$(find_latest 'a*')
    echo $latest
done

上記の仮定が維持されず、ファイルが$dir1、 または$dir2のサブディレクトリにある可能性がある場合を$dir3使用しなければ、findもう少し複雑になります。

find_latest() {
    pattern=$1
    find "$dir1" "$dir2" "$dir3" -name "$pattern" -print0 | xargs -0 ls -t | head -n 1
}

小さな注意事項があります。このhead -n 1ステップでは、パス内の改行文字の後ろの部分が切り捨てられるため、パスに改行文字が含まれていると、この関数は正しく機能しません。そのような道がないことを祈ります;-)

答え2

次の方法でこれを実行できますpax

pax -wrtvZs"|.*/||p" ./DIR[123] "$PWD"

だから私はそれを議論に分解しようとします:

  • -wr- writeとreadは、一緒にpaxファイルをアーカイブするのではなくコピーする必要があることを意味します。コピーを捨てて-l

  • -tpax- メタデータを確認するために、ファイルを読み取る前の状態にすべてのファイルアクセス時間をリセットします。

  • -v- 作業時間が長い。

  • -Z- ソースファイルの変更時間は、可能なすべての名前の置き換えが完了するまで比較されません。

    • これです(そして次に出てくる内容)これにより、すべてが非常に簡単になります。これがなければ - そしておそらく他の場所で直面する問題は - デフォルトの名前を共有してもDIR1/FILEA別のファイルです。DIR2/FILEAだからこれがなければ絶対に比較できないでしょう…
  • -s- ファイル名の一部を標準正規表現に変更しますsed

    • ここでは、各ファイルのすべての部分をデフォルト名に減らしました-Zみんな FILEAsに変更し、最新の内容のみ"$PWD"

私はこれらすべてをチェックするために次のテストを使います。

for d in DIR3 DIR1 DIR2
do  cd ~; mkdir -p "$d"; cd "$d"
    sleep 90; touch FILEB FILEA
done; cd ~

...テストセットを取得します。最終修正時間は次のとおりです。

ls -l ./DIR[123]/FILE[AB]                                
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:28 ./DIR1/FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:28 ./DIR1/FILEB
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./DIR2/FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./DIR2/FILEB
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:26 ./DIR3/FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:26 ./DIR3/FILEB

だから私が実行したとき:

pax -wrtvZs"|.*/||p" ./DIR[123] "$PWD"
ls -l ./FILE[AB]

...出力は...

./DIR1/FILEA >> FILEA
/home/mikeserv/FILEA
./DIR1/FILEB >> FILEB
/home/mikeserv/FILEB
./DIR2/FILEA >> FILEA
/home/mikeserv/FILEA
./DIR2/FILEB >> FILEB
/home/mikeserv/FILEB
./DIR3/FILEA >> FILEA
./DIR3/FILEB >> FILEB

-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./FILEA
-rw-r--r-- 1 mikeserv mikeserv 0 Dec 20 03:29 ./FILEB

あなたはそれが起こっているのを見ることができます。-s|||pファイル名が変更されると、p修飾子はに変わりますstderr。したがって、DIR1ファイルは最初に評価され、にコピーされ、次にファイルは同じ処理を受けますが、ファイルは現在より最新であるためコピーされません$PWDDIR2DIR3$PWD/FILE[AB]

関連情報