定期的に異なるディレクトリにいくつかのファイルを生成するアプリケーションがあり、生成された最新のファイルを確認する必要があります。最新のディレクトリ(作成または更新)で生成されたファイル。ファイルの名前はすべてのディレクトリで同じままなので、ディレクトリを最後に変更されたサブディレクトリに変更する簡単なスクリプトが必要です。
[更新]ほとんどの回答を見て、ディレクトリ名が動的である(ユーザー入力とタイムスタンプに依存する)ことを明確にする必要があると思います。したがって、dir [1、2、3]やのようなディレクトリパターンを想定することはできません。同様
正確に実行したいことやファイルの構造によっては、次のような他の可能性があります。
ls -1tq /dir/*/readme.txt | head -n 1
/ dir /のサブディレクトリ(再帰的ではない)で見つかった最新のreadme.txtのフルネームを返します。
パスの一部(ファイル名の一部としてだけでなく)としての*の使用法はよく知られていないので、言及する価値があると思いました。
file=$( ls -1tq /dir/*/readme.txt | head -n 1 )
cd $( dirname "$file" )
このために複雑なパイプラインは必要ありません。さらに、find
する必要はありません。各ファイルがどこにあるかはすでにわかっているので、どれが最新かはわかりません。これは簡単に処理できます。
デモを行うために、これが私の小さなテストです。
mkdir ./dir1 ./dir2 ./dir3
for d in 1 2 3
do touch ./dir$d/samefile
sleep 1
done
これでテストセットが作成されます。さて、どれが最新ですか?
set -- ./dir[123]/samefile
while [ -e "$2" ]
do [ "$1" -nt "$2" ] &&
set -- "$@" "$1"
shift; done
printf %s\\n "$@"
それは私に教えてくれます。
./dir3/samefile
そして、touch
操作の順序を好きなだけ切り替えることができます。これにより、正しい情報が得られます。必要なのは、次のような関数の小さなシェルループだけです。
newd() { ${2:+:} return 1
while [ -e "$2" ] && [ -e "$1" ]
do [ "$1" -nt "$2" ] &&
set -- "$@" "$1"
shift; done
${2+false} cd "${1%/*}"
}
これはデモとは少し異なるため、引数が2つ未満の場合、または引数が実際のパス名でない場合は確実に失敗することに注意してください。
今、あなたはそれを次のように呼ぶことができます:
newd ./path/to/file1 ./path/to/file2
...など-好きなだけ引数を付けます。
または、私のテストケースでは:
newd ./dir[123]/samefile ; pwd
/home/mikeserv/test/dir3
移植性を高めるために、Perl
を使用できます。
_$ Perl -MList::Util=reduce -le '
BEGIN { $dir = "." }
opendir DIR,$dir;
print shift @{(reduce {$a->[1] > $b->[1] ? $a : $b}
map {[$_,(stat($_))[9]]}
grep { -d and !/^..?$/ }
readdir DIR)}
'
.Skype
_
_$dir
_を検索したいディレクトリに変更します。
どのように機能しますか
readdir
opendir
によって開かれたディレクトリハンドル内のすべてのファイルとディレクトリのリストを返しますgrep { -d and !/^..?$/ }
_:すべてのディレクトリを取得し、_.
_および_..
_ディレクトリをスキップします。map {[$_,(stat($_))[9]]}
:配列を作成します。その要素は、2つの要素を持つ配列参照です:reduce {$a->[1] > $b->[1] ? $a : $b
_:max関数と同様に、配列内の各要素を、変更された時間である2番目の要素と比較します。@{...}
_配列の参照を解除し、shift
ディレクトリ名である最初の要素を取得します。