ディレクトリ内のすべてのデフォルト名を変更された日付でソートする最も信頼性の高い方法は何ですか?

ディレクトリ内のすべてのデフォルト名を変更された日付でソートする最も信頼性の高い方法は何ですか?

以下を含むディレクトリが提供されます。

  • note 1.txt、昨日最後に修正されました
  • note 2.txt、最後の修正は私たちでした
  • note 3.txt、今日最後に修正されました

配列を取得する最良の方法は何ですかnote 3 note 1 note 2

「最高」を定義するために、私は効率性と移植性よりも堅牢性(macOSのZsh環境で)に興味があります。

意図されたユースケースは何百または何千ものプレーンテキストファイルを含むディレクトリですが(質問を混同する危険性があります)、これは私が経験しているより一般的な問題、つまりファイルパスで文字列を実行する特定のケースです。最良の方法はlsfindおよびなどのコマンドを介して印刷することですmdfind


私は上記の目的を達成するためにこのコマンドを呼び出すマクロを使用してきました。

ls -t | sed -e 's/.[^.]*$//'

決して失敗しませんが、

  • グレッグのウィキ出力を解析しないことをお勧めしますls。 (分析するls;実践、'5.絶対にしないでください」。
  • sedパラメータ拡張が可能な場所を呼び出すのは非効率的ですか?

ソートされていないリストを生成する引数拡張find(ファイルパスを安全に区切るには改行ではなく文字を使用)を使用してデフォルト名を抽出します。NUL

find . -type f -print0 | while IFS= read -d '' -r l ; do print "${${l%.*}##*/}" ; done

しかし、変更された日付で並べ替えるには呼び出しが必要なようで、statmacOSsortにはタグがfindないためです。-printfそうでなければうまくいくかもしれません。

最後にZshを使用してください。グローバル予選:

for f in *(om) ; do print "${f%.*}" ; done

移植可能ではありませんが、この最後のアプローチは私にとって最も強力で効率的なようです。これは正しいですfindか?単にディレクトリにファイルを一覧表示するのではなく、実際に検索を実行するときに上記のコマンドの修正版を使用しないでください。

ベストアンサー1

存在するzsh

list=(*(Nom:r))

確かに最も丈夫です。

print -rC1 -- *(Nom:r)

1行に1つずつ印刷する

print -rNC1 -- *(Nom:r)

NULはファイルパスに許可されていない唯一の文字であるため、出力ですべての操作を実行できるようにNULで区切られたレコードとして使用されます。

*(N-om:r)修正時間を考慮するには、次のように変更します。後ろにシンボリックリンクの確認(対象のランタイム、そのようなシンボリックリンクではありませんls -Lt)。

:r(のためcshname)は、拡張を削除するために使用される履歴修飾子です。.bashrcこのオプションが有効な場合にのみ空の文字列になります。dotglob

再帰的に実行されるように変更**/*(N-om:t:r):t(デフォルト名)、つまりディレクトリコンポーネントを削除します。

任意のファイル名を使用してこれを確実に実行することはls困難です。

1つのアプローチは、実行ls -td -- ./*(ファイル名リストが引数リスト制限に準拠していると仮定)し、その出力を解析して各ファイル名がで始まるという事実に基づいて、./NUL区切りリストまたはシェル引用符リストを生成してシェルに渡すことです。しかし、それは移植可能です。また、perlまたはで助けを求めない限り非常に痛いですpython

ただし、信頼できる場合は、perlNULpythonで区切られた出力を使用してファイルのリストを生成してソートすることができます(秒未満の精度をサポートしたい場合は移植するのは簡単ではないかもしれません)。

ls -t | sed -e 's/.[^.]*$//'

改行文字を含むファイル名では正しく機能しません(IIRCの一部のバージョンのmacOSには/etcデフォルトでこれらのファイル名が付属しています)。有効な文字を形成しないバイトシーケンスが含まれているファイル名の場合でも、失敗または.一致しない[^.]可能性があります。ただし、macOSでは機能しない可能性があり、ロケールをC/POSIXに設定して問題を解決できますsed

.()はs/\.[^.]*$//すべての文字に一致する正規表現演算子なので、エスケープする必要があります。それ以外の場合は、ドットのないファイルをfoobar空の文字列に変換します。

文字列の印刷に注意してください。生の、それは:

print -r -- "$string"

print "$string"$stringで始まる値は失敗し、-コマンドインジェクションの脆弱性が発生しても(たとえば、ここでstring='-va[$(uname>&2)1]'無害なunameコマンドを使用しようとすると)文字を含む値を破壊します\

あなたの:

find . -type f -print0 | while IFS= read -d '' -r l ; do print "${${l%.*}##*/}" ; done

もう一つの問題は、あなたが服を脱いだということです.* 今後ディレクトリコンポーネントを削除します。たとえば、aは置き換え./foo.d/barられ、空のfoo文字列にbarなります。./foo

findさまざまなシェルで出力を処理する安全な方法については、以下を参照してください。検索結果を繰り返すのはなぜ悪い習慣ですか?

おすすめ記事