多くのファイルを含むディレクトリがあります。
例:
aaa.txt
bbb.txt
ccc.txt
ddd.txt
ランダムな文字列(必ずしもファイル名である必要はありません)が与えられたら、その文字列の前にソートされたすべてのファイルを見つけたい(通常のアルファベット順にソート)。
例:合計をccc.txt
探したいです。bbb.txt
aaa.txt
ファイル名には通常のASCII文字のみが含まれています。LC_ALL=C
それは推測することができる。隠しファイルがありません(で始まる.
)。
潜在的な解決策は次のとおりです(作成されたテストを含む)。
$ find -isnamelessthan ccc.txt
aaa.txt
bbb.txt
これはどのように達成できますか?
ベストアンサー1
そしてzsh
:
print -rC1 -- **/*(NDe['[[ $REPLY:t < ccc.txt ]]'])
どこ:
print -rC1 --
print
r
sにawおよびon1
C
olumnパラメータがあります。**/
このように、再帰検索のためにすべてのレベルのサブディレクトリ(0を含む)を一致させますfind
。(...)
一致をさらに制限するグローバル修飾子です。N
print
:一致するものがない場合にエラーが報告されず、何も印刷されないようにnullglob:D
:dotglobはと同じで、find
隠しファイルを除外しません。e['code']
:コードを実行してファイルを選択する必要があることを確認してください。ここのコードは、ail(考慮中のファイルパスのデフォルト名)の[[ $REPLY:t < ccc.txt ]]
語彙比較(memcmp()
代わりにロケール認識関数を使用)を実行しますstrcoll()
。t
$REPLY
ccc.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.txt
for のように、開始ファイルへの相対的なファイルパスを./dir/a.txt
NUL バイト (ファイルパスに現れない唯一のバイト値) で区切って印刷します。sort -z
/ globsstrcoll()
に基づいてリストをソートします。ls
LC_ALL=C
(strcoll()
sで使用されているように)を(ASCIIベースのシステムで)に変換します。awk
<
memcmp()
-v RS='\0'
入力R
レコードS
区切り文字をNULバイトに設定します(ORS
新しい行にはデフォルト値を残します)。-F/
、省略形はフィールド区切り記号-v FS=/
をに設定します。F
S
/
$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 .
。