
いくつかの出力レポートを自動化するスクリプトを作成しようとしています。ログファイル(現在および将来の「標準化」予定)は、次のパス構造に保存されます。
/<root_path>/<process_one_path>/logs/<time_date_stamp>/<specific_log_file>
/<root_path>/<process_two_path>/logs/<different_time_date_stamp>/<specific_log_file>
フォルダ内の常に最新のタイムスタンプを除いて、パスのすべての部分が知られています。
タイムスタンプの代わりにワイルドカードを使用しようとすると、次のようないくつかの結果が表示されます。
> ls /<root_path>/<process_two_path>/logs/* [tab]
20130102-175103
20130118-090859
20130305-213506
最新のアイテムだけを返したいです。 Bashでこれは可能ですか?
注(私はzshを持っていません。聞くのは良いですが、仕事で利用できるかどうか疑問です。)
答え1
以下はbash 4.2で動作します。
list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[-1]}"
Bashが以前のバージョンの場合:
list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"
答え2
POSIX的に:
set -- /<root_path>/<process_two_path>/logs/*
shift "$(($# - 1))"
printf '%s\n' "$1"
あなたが言及した後zsh
:
print -r /<root_path>/<process_two_path>/logs/*([-1])
POSIXファイルに隠されていないファイルがない場合、リテラルが出力され、エラーが返され、/<root_path>/<process_two_path>/logs
シェル/<root_path>/<process_two_path>/logs/*
プロセスzsh
は構文エラーのように終了します。君はいつでもできる扱うエラーalways
詰まった、またはN
(についてnullglob
)を使用します。グローバル予選イベントを個人的に処理します。
1 globが外部コマンドの引数にある場合(print
zsh組み込みのためではない)、コマンドを実行するプロセスのみが終了するため、コマンドをキャンセルするように見えます。対話型シェルでは、他の構文エラーのようにシェルを終了するのではなく、プロンプトに戻ります。
答え3
forループを(誤って)使用できます。このように:
for filename in <logdir>/*; do :; done; echo "$filename"
これは、ループが終了した後もループ変数にfilename
まだ最後の値が含まれているために機能します。また、bashはアルファベット順にグローバル拡張を実行するためです。読むバッシュマニュアルより多くの情報を知りたいです。違うので参考にしてくださいLC_COLLATE。
bashはまだ何もせずにすべてのファイルを繰り返す必要があるため、これは最も効率的ではないかもしれません。ただし、合理的な数のファイルを処理するのに十分な速さが必要です。これ以上速度が速くない場合は、ファイル数が多すぎるため、他のアプローチを検討する必要があります。
最も古いタイムスタンプ(最初のソート)を持つファイル名が必要な場合は、次のようにします。
for filename in <logdir>/*; do echo "$filename"; break; done
またはこれ
for filename in <logdir>/*; do break; done; echo "$filename"
これは本質的に同じですが(最初のファイル名を印刷する)、コードとスタイルの設定に応じて他のものよりも優先される可能性があります。
答え4
ls -tr | tail -1
これを行う必要があります。