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)ではないため、これを行わないとします。したがって、これらのメタデータに依存すると、移植性の問題が発生する可能性があります。
有効にした場合は、xattr
OPを編集してこのソリューションを更新できるように明確にしてお知らせください。 zsh
提案されたソリューションは、おそらくシェルを使用するよりも簡単ですbash
。bash
(zsh
とは異なり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}
ブロック内の表示フラグをfound
0に設定BEGIN
($1 ~ /-[rwx-]{9}/ && found == 0)
各レコードに対して、ファイルが通常のファイルかどうかをテストします。この場合、レコードの最初のフィールド()が正規表現と一致する必要があります$1
。いいえ、レコードをスキップして何もしません。-[rwx-]{9}
&&
$path
found
{printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}
このブロックは、レコードをスキップしない限り実行されます。つまり、ファイルは通常のファイルであり、$path
現在処理中のディレクトリ()に表示される最初のファイルです。次に、表示フラグ()を1に設定して、found
同じディレクトリ()内の他のファイルが表示されないようにします。$path
find
ディレクトリツリーが小さくない場合、コードは本質的にホストに依存し、かなりの運用コストがかかります。