私はアプリケーションを作成しており、前提条件の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.log
x*
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
-w
riteとr
eadは、一緒にpax
ファイルをアーカイブするのではなくコピーする必要があることを意味します。コピーを捨てて-l
。-t
pax
- メタデータを確認するために、ファイルを読み取る前の状態にすべてのファイルアクセス時間をリセットします。-v
- 作業時間が長い。-Z
- ソースファイルの変更時間は、可能なすべての名前の置き換えが完了するまで比較されません。- これです(そして次に出てくる内容)これにより、すべてが非常に簡単になります。これがなければ - そしておそらく他の場所で直面する問題は - デフォルトの名前を共有しても
DIR1/FILEA
別のファイルです。DIR2/FILEA
だからこれがなければ絶対に比較できないでしょう…
- これです(そして次に出てくる内容)これにより、すべてが非常に簡単になります。これがなければ - そしておそらく他の場所で直面する問題は - デフォルトの名前を共有しても
-s
- ファイル名の一部を標準正規表現に変更しますsed
。- ここでは、各ファイルのすべての部分をデフォルト名に減らしました
-Z
。みんなFILEA
sに変更し、最新の内容のみ"$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
ファイルは最初に評価され、にコピーされ、次にファイルは同じ処理を受けますが、ファイルは現在より最新であるためコピーされません$PWD
。DIR2
DIR3
$PWD/FILE[AB]