web-dev-qa-db-ja.com

「shopt-sdotglob」を使用する代わりに、「明示的」にすることで、名前がドット(ピリオド)で始まるディレクトリに一致するBashパターン?

_/home/user/project/.git_などのファイル名に一致するパターンを作成する場合、_._文字を「明示的に」、つまり_shopt -s dotglob_を使用せずにどのように一致させますか?

https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html のマニュアルには次のように記載されています。

ファイル名の展開にパターンを使用する場合、シェルオプションdotglobが設定されていない限り、ファイル名の先頭またはスラッシュの直後の文字「。」を明示的に一致させる必要があります。

正確には、「明示的に一致する」とはどういう意味ですか?

また、 http://www.tldp.org/LDP/abs/html/globbingref.html (最後のNotesセクション)でも、同じ概念が取り上げられています。 :

ファイル名の展開はドットファイルと一致できますが、パターンにリテラル文字としてドットが明示的に含まれている場合に限ります。

このメモには、次の例が示されています。

_~/[.]bashrc    #  Will not expand to ~/.bashrc
~/?bashrc      #  Neither will this.
               #  Wild cards and metacharacters will NOT
               #+ expand to a dot in globbing.

~/.[b]ashrc    #  Will expand to ~/.bashrc
~/.ba?hrc      #  Likewise.
~/.bashr*      #  Likewise.
_

「ドットファイル」を含むように拡張される最後の3つの例の内部動作を理解できません。

具体的には、_._の後にbを角かっこで囲むと、例_~/.[b]ashrc_でこれが「明示的な」一致になりますか?以降の例は、私にはさらにあいまいです。 _._文字とはまったく関係がないように見える方法でパターンを操作すると、パターンがどのように一致するのか理解できません。

_shopt -s dotglob_の使用を避けたい理由に関して、この質問のきっかけは、別のプログラムの構成ファイルで使用するためにこれらのパターンを作成しているという事実に根ざしています。たとえば、「非表示の_.git_ディレクトリ」を含むパスを除外したいのですが、dotglobを任意の容量で指定できるかどうかわかりません。

本質的に:「明示的であること」によって_._文字を一致させる最も簡単な手段は何ですか?次の文字を角かっこで囲むと「機能します」が、その理由を知りたいのですが。そのアプローチで「暗闇で撮影」しているような気がします。

この点に関する根本的な振る舞いに関する説明は大歓迎です。

追加する編集:

最初は関連性がないように見えましたが、人々は私のユースケースの詳細に興味を持っているようですので、さらに説明します。

Samhainと呼ばれるホストベースの侵入検知ソフトウェアを使用しています。 Samhainは、特定のユーザー指定の構成パラメーターに従ってファイルシステムが変更されるたびに「アラート」を出します。

_.git_ディレクトリ内のファイル(特定の親ディレクトリ内にある)が作成/変更/削除されたときにSamhainに警告させたくない。サムハインでは、このタイプの除外は「無視ルール」を定義することによって実行されます。これらのルールの正確な仕様は、_4.2. File/directory specification_の http://www.la-samhna.de/samhain/manual/filedef.html で説明されています。

要するに:

Wildcard patterns ('*', '?', '[...]') as in Shell globbing are supported for paths. The leading '/' is mandatory.

そのため、問題の_.git_ディレクトリに一致する「無視ルール」を作成しようとしています。これにより、Samhainは監視アクティビティからそれらを除外します。

最初に、私はこれを試しました:

_[IgnoreAll]
dir = -1/home/user/project/*/*/.git
_

これは機能しませんでした。それらの_.git_ディレクトリ内のファイルが変更されるたびにSamhainは引き続き警告を発しました。

上で引用した例を見つけたら、私はこれを試しました:

_dir = -1/home/user/project/*/*/.[g]it
_

この変更により、Samhainは必要に応じてファイルを無視します。

この質問を投稿する際に、私は単にその変更が意図した効果をもたらす理由を理解しようとしていました。

私が最初に使用しようとしていたパターンそのものが、「エコー」テストを使用するときに問題の_.git_ディレクトリと実際に一致することを考えると、私はそれほど愚かではないと言います。

_echo /home/user/project/*/*/.git
_

したがって、Bashでのパターンマッチング、グロブ、またはファイル名の拡張に関して、基本的なことを誤解していることはそれほど多くありませんでした。それどころか、特にサムハインがこの文脈でパターンマッチングをどのように実装するかに関しては微妙な違いがあるようです。

Samhainの構成ファイルのコンテキストで適用したときにこれが機能しない理由がわかりません(明らかに)。この編集があれば、誰かが説明できるかもしれません。

1
Ben Johnson

まず、パス名パターンで[b]?*などが何を意味するかを知っていると思います。 (そうでない場合は、さらに調査を行ってください。)

他の人が言ったことを繰り返すリスクを冒して、あなたはそれを考えすぎています。文字列/.を含むパターン(つまり、/immediatelyの後に.が続く)は、リテラルとしてドットを明示的に含みますキャラクター。重要なのは、[b]?および/または*が発生することです.影響しないパターンがドットファイルと一致できるかどうか。最後の3つの例は、~/.bashrcに一致するpatterns(つまり、プレーンファイル/パス名だけでなく、複数のファイル/パス名に一致する可能性のあるもの、またはまったく一致しないもの)の例として提供されています。 —最初の2つとは対照的に、~/.bashrcが特別に処理されなかった場合、would.と一致します。

それで、あなたの本当の質問は何ですか?

…別のプログラムの構成ファイルで使用するために、これらのパターンを作成しています。たとえば、「非表示の.gitディレクトリ」を含むパスを除外したいのですが、dotglobを任意の容量で指定できるかどうかわかりません。

すべてのファイル/ディレクトリに対して(chowncpなど)何かをしたいと思いますexceptドットで始まるもの。しかし、あなたのコードは他の誰かのスクリプトで(.またはsourceコマンドを介して)使用されることになり、your_command *を実行することを恐れています。スクリプトがdotglobを設定している可能性があるため、*は「非表示」ファイルを含むすべてのファイルに展開されます。また、既存のスクリプトの機能を壊したくないので、dotglobをオフにしたくありません。

  1. よりスマートなワイルドカード(パス名拡張パターン)を使用します。

    [abc]のようなワイルドカード(別名グロブ)を理解していただければ幸いです。ワイルドカードは、ab、またはcのいずれかの文字と一致します。たとえば、文字列c[aou]tcatcot、およびcutと一致します。 d[iou]gDigdog、およびdugと一致します。 (これらは範囲で使用でき、通常は使用されます。たとえば、[a-z]および[0-9]です。)まあ、これの特殊なケースは[!abc]です—任意の文字に一致します例外abまたはc。したがって、[!.]*(またはdirectory_name/[!.]*)を使用して、ドット以外の文字で始まる名前を照合できます。逆説的ですが、dotglobが設定されていない場合、[.](ファイル名の先頭)はドットと一致しませんが、[!.]excludeドットとは関係ありませんdotglobの設定の.

    これにより、dotglobが設定されているかどうかに関係なく同じ結果が得られます。

  2. dotglob(サブシェル内)を使用します。

    シェルオプション(shopts)はプロセスに対してローカルであり、プロセス属性が子から親に逆方向(上り坂)に流れることはありません。そう

    (shopt -u dotglob; your_command *)
    は、スクリプトの残りの部分の設定や動作に影響を与えることなく、隠しファイル以外のファイルでのみ実行されますyour_command
  3. dotglobを使用します(サブシェルを使用せずに)。

    余分なリソースを使用するため、サブシェルを避けることを好む人もいます。ただし、コストはごくわずかであるため(many回実行するループで実行しない限り)、これはあまり適切な理由ではありません。サブシェルを回避するより良い理由は、cdumaskなどのシェルの環境に影響を与える何かをする必要がある場合です。

    このような状況の場合は、一時的にdotglobをオフにして、後で以前の設定に戻すことができます。

    shopt dotglob-sまたは-uなし)と入力すると、dotglobオプションの現在の設定が報告(表示)されます。 (shopt with no parametersは、allオプションの現在の設定を一覧表示します。)また、それに応じて終了ステータスを設定します。 -qフラグは表示を抑制するため、次のことができます。

    shopt -q dotglob 
     dotglob_setting = $?
     shopt -u dotglob 
    your_command * 
     if ["$ dotglob_setting" = 0] 
     then 
     shopt -s dotglob 
     fi

しかし待ってください…「別のプログラムの構成ファイル」とおっしゃいました。あなたは何について話していますか? ignore=*.oのようなファイルの作成または変更について話している場合、そのファイルはどのプログラムでも処理(および解釈)されるため、この質問全体は意味がありません。 そのプログラム*の解釈方法を決定します—シェルはそれとは何の関係もありません。


さて、質問が何であるかについてのより良い考えができたので:

簡単に言えば、あなたが見ている行動は意味をなさないということです。 .gitディレクトリが存在する場合、それを.gitとして正確に(文字通り)指定し、.[g]itのワイルドカード/グロブパターンで指定すると同じように動作するはずです。

長い答え:私は私の答えの最初のバージョンの最後の段落を支持します。 Samhainは、ポリシー構成ファイルを読み取って解析しています。シェルを使用して構成ファイル内のワイルドカードを解釈する場合がありますが、内部で実行していると思います。

また、「シェルを使用している」場合、どのシェルを使用していますか?多くのシステムでは、/bin/shはbashではありません。パス名の展開パターン(ワイルドカードなど)に関するベースラインの動作は同じである必要がありますが、ポーチを降りると沼地になります。シェルのPOSIX仕様にはshoptコマンドすらなく、(AFAIK)には*allファイルに展開する方法がありません(および非表示のものだけではありません)。

あなたが好きなら 無駄に これにもう少し時間をかけて、/home/user/project/*をSamhain構成ファイルに入れて、それがすべてのファイルとして解釈されるのか、非表示でないファイルとして解釈されるのかを確認してみてください。それがすべてのファイルとして解釈される場合、私たちは結論を下すことができます

  1. Samhainは、ワイルドカードを展開するために/bin/shを使用していません。
  2. ワイルドカード(質問でそのような長さで説明したもの)には、標準のデフォルトのルールは使用されていません。
  3. 「シェルグロブのようなワイルドカードパターン(「*」、「?」、「[...]」)はパスでサポートされている」と書かれている限り、ドキュメントは間違っています(または、せいぜい不完全で誤解を招く可能性があります)。言うまでもなく(シェルのデフォルトの動作とは異なり)*はすべてのファイルを意味します。
  4. mightdotglobモードでbashを使用してワイルドカードを展開しています。しかし、これは意味がありません。すでに述べたように、.git.[g]itの処理は、私が知っているシェルの通常の動作に対応していません。ほぼ確実に、ワイルドカード用の独自のコードがあります。

しかし、いずれにせよ、あなたの結論は正しいと自信を持って言えると思います。Samhainには、IgnoreAll仕様でのワイルドカードの処理に関してバグがあります。ベンダーにバグレポートを提出することをお勧めします。または、回避策を見つけたので、それを忘れることができます。

ファイル名の展開にパターンを使用する場合、シェルオプションdotglobが設定されていない限り、ファイル名の先頭またはスラッシュの直後の文字「。」を明示的に一致させる必要があります。

これは単に、グロブ*?、および[...]がファイル名の先頭の.と一致しないことを意味します。ファイル名の先頭にある.と一致させたい場合は、globを使用できません。明示的に.を入力する必要があります。例えば:

$ echo ????
Work
$ echo .???
.gem .pki .ssh .vim

そしてあなたの他の質問に答えるために:

具体的には、.の後にbを角かっこで囲むと、例~/.[b]ashrcでこれが「明示的な」一致になりますか?

グロブパターンを使用しているからといって、wholeパターンが「明示的」ではなくなったわけではありません。たとえば、~/.[b]ashrcでは、文字/.ashrcはすべて明示的に一致します。ただし、[b]はグロブパターンであり、明示的な一致でもありません。 (技術的には、~はチルダ展開であり、glob展開よりも前に実行されるため、明示的に一致します。)ただし、.do一致を含む他の文字明示的に、これが~/.[b]ashrc~/.bashrcと一致する理由です。

比較のために、~/?[b]ashrcは明示的に一致しなくなったため、~/.bashrcnot.と一致します。

7
jayhendren