指定されたファイルの前にソートされたファイルを探す

指定されたファイルの前にソートされたファイルを探す

多くのファイルを含むディレクトリがあります。

例:

aaa.txt
bbb.txt
ccc.txt
ddd.txt

ランダムな文字列(必ずしもファイル名である必要はありません)が与えられたら、その文字列の前にソートされたすべてのファイルを見つけたい(通常のアルファベット順にソート)。

例:合計をccc.txt探したいです。bbb.txtaaa.txt

ファイル名には通常のASCII文字のみが含まれています。LC_ALL=Cそれは推測することができる。隠しファイルがありません(で始まる.)。

潜在的な解決策は次のとおりです(作成されたテストを含む)。

$ find -isnamelessthan ccc.txt
aaa.txt
bbb.txt

これはどのように達成できますか?

ベストアンサー1

そしてzsh

print -rC1 -- **/*(NDe['[[ $REPLY:t < ccc.txt ]]'])

どこ:

  • print -rC1 -- printrsにawおよびon 1 Columnパラメータがあります。
  • **/このように、再帰検索のためにすべてのレベルのサブディレクトリ(0を含む)を一致させますfind
  • (...)一致をさらに制限するグローバル修飾子です。
    • Nprint:一致するものがない場合にエラーが報告されず、何も印刷されないようにnullglob:
    • D:dotglobはと同じで、find隠しファイルを除外しません。
    • e['code']:コードを実行してファイルを選択する必要があることを確認してください。ここのコードは、ail(考慮中のファイルパスのデフォルト名)の[[ $REPLY:t < ccc.txt ]]語彙比較(memcmp()代わりにロケール認識関数を使用)を実行しますstrcoll()t$REPLYccc.txt

GNUシステムでは、(すべてのシェルで)次のコマンドを使用して同様の操作を実行できます。

find . -mindepth 1 -printf '%P\0' | sort -z |
  LC_ALL=C gawk -v RS='\0' -F/ '$NF < "ccc.txt"'

どこ:

  • -mindepth 1、スタートアップファイル(.)を除外します。! -name .他のスタートアップファイル²には展開されませんが、標準を使用することもできます。
  • -printf '%P\0'dir/aaa.txtfor のように、開始ファイルへの相対的なファイルパスを./dir/a.txtNUL バイト (ファイルパスに現れない唯一のバイト値) で区切って印刷します。
  • sort -z/ globsstrcoll()に基づいてリストをソートします。ls
  • LC_ALL=Cstrcoll()sで使用されているように)を(ASCIIベースのシステムで)に変換します。awk<memcmp()
  • -v RS='\0'入力RレコードS区切り文字をNULバイトに設定します(ORS新しい行にはデフォルト値を残します)。
  • -F/、省略形はフィールド区切り記号-v FS=/をに設定します。FS/
  • $NF < "ccc.txt":最後のフィールドを"ccc.txt"語彙と比較し、trueの場合は、デフォルトジョブ({print}略語{print $0})を実行してレコードを印刷します。

述語の場合は、-isnamelessthan find次のことができます(zshから)。

alias -g -- -isnamelessthan='-exec zsh -c "[[ \$1:t < \$2 ]]" zsh {}'

次のように使用されます。

find . -isnamelessthan ccc.txt ';' -print

(各ファイルを確認するために1つのインスタンスを実行するので、効率的ではありませんzsh。)


¹ glob 自体はロケールに従ってソートされているので、次のようにします。strcoll()

find /path/to/dir ! -name dir²内部的に呼び出されるファイルを除外するため、これはできませんが、dir実行できますfind /path/to/dir/. ! -name .

おすすめ記事