web-dev-qa-db-ja.com

現在のディレクトリの最後に変更されたサブディレクトリに移動します

定期的に異なるディレクトリにいくつかのファイルを生成するアプリケーションがあり、生成された最新のファイルを確認する必要があります。最新のディレクトリ(作成または更新)で生成されたファイル。ファイルの名前はすべてのディレクトリで同じままなので、ディレクトリを最後に変更されたサブディレクトリに変更する簡単なスクリプトが必要です。

[更新]ほとんどの回答を見て、ディレクトリ名が動的である(ユーザー入力とタイムスタンプに依存する)ことを明確にする必要があると思います。したがって、dir [1、2、3]やのようなディレクトリパターンを想定することはできません。同様

2
Jay

正確に実行したいことやファイルの構造によっては、次のような他の可能性があります。

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
4
mikeserv

移植性を高めるために、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_を検索したいディレクトリに変更します。

どのように機能しますか

  • readdiropendirによって開かれたディレクトリハンドル内のすべてのファイルとディレクトリのリストを返します
  • _grep { -d and !/^..?$/ }_:すべてのディレクトリを取得し、_._および_.._ディレクトリをスキップします。
  • map {[$_,(stat($_))[9]]}:配列を作成します。その要素は、2つの要素を持つ配列参照です:
    • 最初はディレクトリ名です
    • 秒は変更された時間です
  • _reduce {$a->[1] > $b->[1] ? $a : $b_:max関数と同様に、配列内の各要素を、変更された時間である2番目の要素と比較します。
  • _@{...}_配列の参照を解除し、shiftディレクトリ名である最初の要素を取得します。
1
cuonglm