私のホームディレクトリにあるいくつかの隠しファイルを一覧表示しようとしていますが、コマンドとgrep
組み合わせると非常に奇妙なコマンド動作が発生しますls
。
ls -a
私のホームディレクトリから実行し、隠されたファイルを含む予想どおりにすべてのファイルを取得しました。- すべて一覧表示したい隠しファイル「xau」で始めて実行してみましたが、
ls -a |grep -i .xau*
やはり予想通りに動作しましたね。 - その後、
ls -a |grep -i .x*
同じディレクトリで実行しますが、まったく何もリストされていません。 - それでは私が誤って入力したのです。
ls -a |grep -i .*x
(今回はワイルドカード文字*と文字「x」が位置を変えました。)興味深いことに、ステップ3で期待どおりに機能します。このコマンドで同じことを試しls -a .*x
ましたが、ls -a .*X
そのファイルやディレクトリはありません。間違い。
実際のテキスト出力を追加しました。ここで。
なぜ直接使用しないのかという方もいらっしゃるでしょうが、ls -a .x*
適切なgrep
色が出力されます。だから誰かが私にこれを説明できますか?
答え1
あなたは苦しんでいます早期グローバル拡張。
.xa*
現在、ディレクトリ内のどの項目とも一致しないため、拡張されません。 (Globは大文字と小文字を区別します。).x*
する特定のファイルと一致するため、シェルはファイルをgrep
表示する前にそのファイルを展開します。
複数の引数を受け取ると、最初の引数がパターンであり、残りの引数がそのパターンをgrep
検索するファイルであると仮定します。
したがって、コマンドのls -a | grep -i .x*
出力は次のようにls
なります。無視される、「.xsession-errors」パターンの「.xsession-errors.old」ファイルを検索します。当然、何も見つかりませんでした。
これを防ぐには、一重引用符または二重引用符で特殊文字を囲みます。たとえば、
ls -a | grep -i '.x*'
あなたも苦しんでいます。正規表現とglobの間の混乱。
リテラル文字列 ".x"で始まり、その後に何も来るファイルを探しているようですが、正規表現はファイルワイルドカードと同じようには機能しません。これ*
正規表現としてファイルglobと同様に、「文字の順序」ではなく「0個以上の先行文字」を意味します。あなたはどうですか?おそらくあなたが望むもの:
ls -a | grep -i '^\.x'
次の名前のファイルを検索します。スタートリテラル文字「.x」または「.X」を使用します。実際には文字だけを指定するので、代わりに文字クラスを簡単に使用できます-i
。
ls -a | grep '^\.[xX]'
ポイントは正規表現はファイルグローブとは大きく異なります。
提案どおりに試してみると、ls -a | grep -i '.x*'
すべてのファイルが表示されるという事実に非常に驚くでしょう! (直接出力と同じで、ls -a
と同様に別々の行にありますls -a -1
。)
どうですか?
まあ正規表現(しかしシェルグローブではない)ピリオド(.
)は「すべての単一文字」を意味します。アスタリスク(*
)は「0個以上の先行文字」を意味します。したがって、正規表現は、.x*
「 'x'文字のインスタンスがゼロ以上の後に続くすべての文字」を意味します。
もちろん、ファイル名が空でなければなりません。すべてファイル名には、「文字の後に少なくとも0個の 'x'が続きます」が含まれています。 :)
要約:
必要な結果を得るには、次の2つを知る必要があります。
- 引用符のない特殊グローバル文字(および
*
その他の一部の文字を含む)が拡張されます。?
[]
シェルを通してコマンドを実行する前により彼らと - 正規表現はファイルグローブとは異なり、より強力です。
答え2
問題は、*
周囲に引用符を入れずにコマンドを実行する前にシェルを拡張することです。望むより:
$ touch .xau1 .xau2
# this won't work
$ ls -a | grep -i .xau*
# but this does
$ ls -a | grep -i ".xau*"
.xau1
.xau2
# this one too
$ ls -a | grep -i '.xau*'
.xau1
.xau2
# check what shell sees
$ ls -a | grep -i .xau* # now don't press enter but C-x * and you'll see this:
$ ls -a | grep -i .xau1 .xau2