web-dev-qa-db-ja.com

Findステートメントの結果を日付で並べ替える方法は?

名前に特定の文字列を含むファイルを見つけようとしますが、出力をソートする方法がわからないので、ファイル名のみを取得します。

私はもう試した

OLDDATA=`find . -regex ".*/[0-9.]+" | ls -t`

しかし、ls -tは検索結果ではなくディレクトリ全体で機能します

編集:このステートメントの結果は、変更日のディレクトリでソートする必要があります。この正規表現は、名前に数字とドットのみを含むディレクトリに一致すると想定しています。

5
harcotlupus

ファイル名のみを取得...変更日でソート

find + sort + cutアプローチ:

find . -regex ".*/[0-9.]+" -printf "%T@ %f\n" | sort | cut -d' ' -f2

  • %T@-ファイルの最終変更時刻。ここで、@は、小数部を含むJan. 1, 1970, 00:00 GMT,からです。

  • %f-先頭のディレクトリが削除されたファイルの名前(最後の要素のみ)


降順で並べ替えるには:

find . -regex ".*/[0-9.]+" -printf "%T@ %f\n" | sort -k1,1r | cut -d' ' -f2
7
RomanPerekhrest

あなたの方法は単純なケースで機能するように適応させることができます。あなたが直面している主な問題は、inputlsに渡していますが、lsは入力を受け取りません。 lsはコマンドライン引数を取ります。したがって、findの出力をargumentsとしてlsにコマンド置換で渡す必要があります。また、ディレクトリが一致する場合は、-dlsに渡して、ディレクトリではなくディレクトリ自体をリストします。

OLDDATA=$(ls -td $(find . -regex ".*/[0-9.]+"))

2つの制限があるため、単純な場合のみ:

  1. これは 引用符で囲まれていないコマンド置換 に依存します(その後の$OLDDATAの使用も同様です)。したがって、ファイル名に特殊文字(空白またはワイルドカード文字\[*?)が含まれていないと想定しています。
  2. lsの一部のバージョンでは、現在のロケールでは印刷できない文字が破損する場合があります。
  3. ファイル名の合計が長すぎると、エラーが発生します。 (xargsはファイル名の順序を正しくするために1回実行する必要があるため、find … -execlsはここでは役に立たないことに注意してください。エラーを非表示にし、正しくソートされていない出力— xargsの場合は、さらにいくつかの文字をマングルします。)

これを行うための堅牢で簡単な方法は、 zsh を使用することです。 glob qualifiers のおかげで、ワイルドカードの一致をソートすることができます。

setopt extended_glob
OLDDATA=(**/[0-9.]##(om))
  • これは他のプログラムを呼び出さないため、使用可能なメモリ以外の長さの制限はなく、ファイル名がどの時点でも変更されるリスクはありません。
  • 結果は文字列ではなく、文字列(各文字列はファイル名)のlistなので、配列変数に入ります。
  • **/は、findの使用を避けて、サブディレクトリを再帰的にトラバースします。
  • ##は、zsh拡張グロブ構文で「前述の1つ以上」を意味し、(拡張)正規表現構文の+に類似しています。
  • (om)は、ls -tのように、変更時刻でファイルをソートするためのグロブ修飾子です。

これをPOSIXツールで確実に、またはGNU toolsおよびkshでも)実行する簡単な方法はありません。