要約:
- 特定のシステムには、名前を含む多くのテキストファイルがあります
~=
[type of file].[8-digit date]
。 - これらのファイルを検索するには、次の慣用語を使用することをお勧めします(そして維持したい)。 (
find /path/ -name 'file.nnnn*' -print | xargs -e fgrep -nH -e 'text I seek'
ここでnnnn
==年は4桁) - ...過去10年間、私は
find
長年にわたってグローバルコラボレーションを行いました。find /path/ -name 'file.201[89]*' -print | xargs ...
find
...しかし、2019年と2020年には使用できません。find /path/ -name 'file.20{19,20}*' -print | xargs ...
- ...「中かっこワイルドカード」(正確な用語?)はうまく機能しますが
ls
!
find
事後整理せずに何をしたいのかfind
(例:私が今やっていること)を知らせる{簡潔でエレガントな}方法はありますか?
find /path/ -name 'file.*' -print | grep -e '\.2019\|\.2020' | xargs ...
? FWIW、私はxargs
。
詳細:
私が取り組んでいるシステムには、以前から存在しており、変更できない多くの慣習があります。その1つは、~=
[type of file].[8-digit date]
たとえばという名前のテキストファイルがたくさんあることです。私は通常、woohoo_log.20191230
このファイルから特定のテキストを検索するときに慣用語find ... grep
(通常はEmacsを使用M-x find-grep
)を使用します。 (FWIW、これはLinuxシステムです。
$ find --version
find (GNU findutils) 4.4.2
...
$ bash --version
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
現在、必要に応じて変更できる状態はありません。 )私はしばしば現在の仕事の年の範囲を知っているので、find
(作業速度を上げるために)返される項目を制限しようとします。
find /path/ -type f -name 'file.nnnn*' -print | xargs -e fgrep -nH -e 'text I seek'
ここでnnnn
== 4桁の年です。私の好きな(そして維持したい)このWFMは上記のイディオムを使います。特に長年の検索にも使えるからです。
find /path/ -type f -name 'file.201[89]*' -print | xargs ...
しかし、新しい10年が経つにつれて、そのような習慣が壊れているようで、(少なくとも私にとっては)最も奇妙なことはこれです。 (過去10年間で状況が変わったとき、私はここにいませんでした。)私が望むテキストを選択するとしましょう。知る2019年ファイル&&2020年ファイルにあります(つまり、ファイルを開いてテキストを表示できます)。私が今これをするなら
find /path/ -name 'file.20{19,20}*' -print | xargs ...
grep
予期しない/迷惑なことをしたwith no matches found
理由は次のとおりです。
$ find /path/ -name 'file.20{19,20}*' -print | wc -l
0
しかし、私がそうするなら
find /path/ -type f -name 'file.*' -print | grep -e '\.2019\|\.2020' | xargs ...
grep
期待される結果を返します。いいのに…うーん…特にこの「中かっこグローブ」のため見苦しいです(この使い方が正しくないか、もう使われていない場合は修正してください) 仕組みls
!つまり、関連する年の範囲内(たとえば、2019..2020)内の文書が表示されます。
ls -al /path/file.20{19,20}*
したがって、私は知りたいです:
find
このユースケースに正しいglobを提供していませんか?それができる/正しいことをfind
するために何を言うべきですか?ls
- これが問題ですか
xargs
?そのfind ... -exec
場合は解決策を受け入れることができますが...私の脳は同じ状況でうまく機能するので、可能であればそれに固執することをお勧めしますxargs
。 (私は精神遅滞者と言えますが、-exec
文法は脳を痛める.)
答え1
を使用すると、10進数の範囲に一致するzsh
再帰ワイルドカードと対応するワイルドカード演算子を使用できます。<x-y>
grep -nHFe 'text I seek' /path/**/file.<2019-2020>*(D-.)
(隠しディレクトリも表示(D)
できます。望まない場合は、おそらく省略して次のように制限できます。D
find
-.
定期的なファイル(.
)はシンボリックリンク解析()の後に識別されます-
。
これはon file.00002020
(2019から2020の間の10進数であるため)とも一致し、onメソッドと同様にwhich matchと一致しますfile.20201234
。file.2020
file.<2019-2020>
1234
*
標準(POSIXsh
とユーティリティ)のアプローチは次のとおりです。
find /path \( -name 'file.2019*' -o -name 'file.2020*' \) -type f \
-exec grep -Fne 'text I seek' /dev/null {} +
(追加された効果は/dev/null
GNUのファイル名の強制表示と同じです。)grep
-H
の出力は、find -print
の予想入力形式と互換性がありませんxargs
。 GNUユーティリティを使用するとfind -print0
およびを使用できますが、動作は同じで、より短く、移植性が高いxargs -r0
ため、必須ではありません。find -exec ... {} +
答え2
とは関係ls -al /path/file.20{19,20}*
ありません。このコマンドでは、シェルは次を実行します。ls
{19,20}*
支柱の拡張そしてワイルドカード/path/file.20{19,20}*
〜のように参照されません:
bash-5.0$ set -x
bash-5.0$ echo {a,b}
+ echo a b
a b
bash-5.0$ ls {a,b}
+ ls a b
ls: cannot access 'a': No such file or directory
ls: cannot access 'b': No such file or directory
bash-5.0$ find -iname {a,b}
+ find -iname a b
find: paths must precede expression: `b'
はに引用されているfind /path/ -name 'file.20{19,20}*'
ので、'file.20{19,20}*'
シェルはそれを無視してfind
自己適用します。パターンマッチングルール、中かっこ拡張をサポートしていません。ここに引用GNUfind
マニュアル:
パターン( ' ')
{}
内の中かっこは特殊なものとして扱われません(find . -name 'foo{1,2}'
例:foo{1,2}
ファイルfoo1
とfoo2
。
中かっこ拡張を使用してディレクトリを再帰的に検索するには、bashで再帰的グローブを有効にできます(globstar
)(おそらくdotglob
このような隠しディレクトリを見ることができますfind
)printf
次のように使用しますxargs
。
shopt -s globstar
printf "%s\0" /path/**/file.20{19,20}* | xargs -0 ...
あるいは、一部の実装でサポートする代わりにfind
withを使用することもできます。 GNUの使用:-regex
-name
find
find
find /path -regextype posix-extended -regex '.*/file.20(19|20)[^/]*'
答え3
これはあなたの質問に対する一般的な答えではありませんが、あなたが持っているファイルの履歴の量に応じて簡単な方法があるかもしれません。私は9月または10月に物事を見つけるとき、同様の状況によく直面します。簡単な回避策は、次のパターンを使用することです。
file.20[12][90]*
2019年と2020年のほか、2010年と2029年も一致するため、同じではありません。おそらく、2029年の日付の文書はまだありません。アーカイブが2010年に戻らない場合は、機能的に同じでなければなりません。