Bashを使用してフォルダサブツリーの各レベルで「最新」のパス、ファイル名、日付と時刻を検索する[閉じる]

Bashを使用してフォルダサブツリーの各レベルで「最新」のパス、ファイル名、日付と時刻を検索する[閉じる]

Bashを使用して、指定されたディレクトリとそのサブツリーのファイル名、そのディレクトリに生成された最後のファイルの作成日、および作成時間を見つけたいと思います。たとえば、出力は次のようになります。

/home/dir    filename0  creation_date0 creation_time0
/home/dir/subdir1    filename1  creation_date1  creation_time1
/home/dir/subdir2    filename2  creation_date2  creation_time2

答え1

努力する:

$ find /path/to/dir -type d -print0 | xargs -0 -I{} bash -c '
    path="{}";
    ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" | \
    awk -v dir="$path" '\''BEGIN {found=0} ($1 ~ /-[rwx-]{9}/ && found == 0) {printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}'\'';'

タブ区切りの「absolute_path」、「filename」、「last_modif_date」、「last_modif_time」を使用した出力例:

/path/to/dir/otp_src_19.1/lib/ic/src    icparse.erl     2016-09-20        21:56:21
/path/to/dir/otp_src_19.1/lib/dialyzer  AUTHORS 2016-09-20        21:11:23
/path/to/dir/otp_src_19.1/lib/dialyzer/doc      about.txt       2016-09-20     21:11:23

レビュー2:

  • 上記の回避策は、最新の「作成」または「作成」日時ではなく、最新のファイル状態の変更日時に基づいています。作成日時に基づいてファイルを区別するには、次のものが必要です(拡張属性) このシステムで有効になっています。標準の問題(POSIX)ではないため、これを行わないとします。したがって、これらのメタデータに依存すると、移植性の問題が発生する可能性があります。
    有効にした場合は、xattrOPを編集してこのソリューションを更新できるように明確にしてお知らせください。
  • zsh提案されたソリューションは、おそらくシェルを使用するよりも簡単ですbashbashzshとは異なりls *(.))リストのみ一般ファイルでは不可能ですls。つまり、次のことを行うフラグやオプション、特殊なグロービングパターンはありませんls --regular-file-only。したがって、ファイルを一覧表示すると、ls [options]一般ファイル、リンク、およびディレクトリが作成され、$PWD一般ファイルはそれらからフィルタリングする必要があります。

仕組み:

  • find /path/to/dir -type d -print0で始まるディレクトリのサブツリーで、すべてのディレクトリを探します/path/to/dir。ディレクトリ名の空白の問題を避けるために、標準行末文字を NULL に置き換えて各ディレクトリを印刷します。これは次にパイプされます。
  • xargs -0 -I{} bash -c '...'標準入力(ここで標準入力はパイプ入力データに置き換えられます)から入力結果を読み取り、それを次のミニBashスクリプトに表示します。
    • ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" |-AF「ほとんどすべて」()ファイルを長い形式で一覧表示し、グループ(-o)情報なしで渡されたディレクトリのファイルタイプに関係なく、次の操作を行います$path
      • --time-style=+"%Y-%m-%d %H:%M:%S"最後のディレクトリ状態の変更日付/時刻を次の手順()で簡単に解析できるように、リストされたファイル出力()の形式を指定します。--time=ctimeファイルのディレクトリ状態の変更時間は、ファイル自体の変更時間と異なる場合があります。
      • 表示された修正時間()に基づいて最新の項目から-tファイルをソートします。
      • パイプ形式と並べ替えられた出力を次のawkフィルタに送信します。
    • awk -v dir="$path" '...'
      • $path内部awk変数に値を割り当てます。dir
      • BEGIN {found=0}ブロック内の表示フラグをfound0に設定BEGIN
      • ($1 ~ /-[rwx-]{9}/ && found == 0)各レコードに対して、ファイルが通常のファイルかどうかをテストします。この場合、レコードの最初のフィールド()が正規表現と一致する必要があります$1。いいえ、レコードをスキップして何もしません。-[rwx-]{9}&&$pathfound
      • {printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}このブロックは、レコードをスキップしない限り実行されます。つまり、ファイルは通常のファイルであり、$path現在処理中のディレクトリ()に表示される最初のファイルです。次に、表示フラグ()を1に設定して、found同じディレクトリ()内の他のファイルが表示されないようにします。$path

findディレクトリツリーが小さくない場合、コードは本質的にホストに依存し、かなりの運用コストがかかります。

関連情報