シェルワイルドカード文字の拡張を停止しますか?


88

コンパイルされたコマンドラインプログラムがbashまたはcshに、パラメーター内のワイルドカード文字を展開したくないことを通知する方法はありますか?

たとえば、次のようなシェルコマンドが必要になる場合があります。

foo *

その文字のASCII数値を返すだけです。

回答:


117

いいえ。拡張は、コマンドが実際に実行される前に行われます。
コマンドを実行する前、または星を引用することによってのみ、グロブを無効にすることができます。

$ # quote it
$ foo '*'

$ # or escape it
$ foo \*

$ # or disable the glob (noglob)
$ set -f
$ foo *

$ # alternative to set -f
$ set -o noglob
$ # undo it by 
$ set +o noglob

3
また、拡張するものがない場合、拡張はありません。つまり、空のpwd場合echo *は、ちょうど*
sam boosalis 2014年

7
@samこれは、実際にはオプションの設定方法によって異なります。tldpから:「一致するファイル名が見つからず、シェルオプションnullglobが無効になっている場合、単語は変更されません。nullglobオプションが設定されていて、一致するものが見つからない場合、単語は削除されます。」
クリスミドルトン

おかげで、私はそれが理解からではなく観察からのものであると認定すべきでした。
sam boosalis 2015

@ c00kiemon5ter元に戻す方法はset -f?それunset -fですか?
ナム

1
@NamGVUset +f
Yngvar Kristiansen

62

コマンド自体がグロブをオフにすることはできないのは事実ですが、ユーザーが特定のコマンドをグロブしないようにUnixシェルに指示することは可能です。これは通常、シェルの構成ファイルを編集することによって実現されます。コマンドfooがコマンドパスに沿って見つかると仮定すると、適切な構成ファイルに以下を追加する必要があります。

sh、bash、kshシェルの場合:

alias foo='set -f;foo';foo(){ command foo "$@";set +f;}

cshおよびtcshシェルの場合:

alias foo 'set noglob;\foo \!*;unset noglob'

zshシェルの場合:

alias foo='noglob foo'

コマンドパスを使用する必要はありません。コマンドfooがディレクトリ〜/ binに格納されているとすると、上記は次のようになります。

sh、bash、kshシェルの場合:

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

cshおよびtcshシェルの場合:

alias foo 'set noglob;$home/bin/foo \!*;unset noglob'

zshシェルの場合:

alias foo='noglob ~/bin/foo'

上記のすべては、AppleのOSX10.9.2を使用してテストされました。注:上記のコードをコピーするときは、スペースの削除に注意してください。それらは重要かもしれません。

更新:

ユーザーgeiraは、bashシェルの場合はそれを指摘しています

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

で置き換えることができます

reset_expansion(){ CMD="$1";shift;$CMD "$@";set +f;}
alias foo='set -f;reset_expansion ~/bin/foo'

これにより、関数fooが不要になります。

このドキュメントの作成に使用されたいくつかのWebサイト:


3
OPが望んでいることを実際に行うことが可能であることを証明しているので、これは受け入れられた答えであるはずです。bashのさらに優れた方法については、次のリンクにさまざまなオプションが記載されています。blog.edwards
research.com

@geira:より良い回答が投稿される前に、回答が受け入れられることがあります。これもその一つかもしれないと思います。また、ユーザーにとって最も役立つ回答マークが最初に表示されると思います。注:私はあなたの意見を私の答えに追加しました。
デビッドアンダーソン

@ geira、OPは、コンパイルされたプログラムがシェルと通信することを望んでいます。コマンドごとに希望どおりに動作するようにシェルを構成できると答えることは有用な答えであり、私自身もこれを受け入れますが、それが完全に適切であるかどうかについては意見が分かれる余地があります。
チャールズダフィー2015

それができるという事実は、それなされるべきであるという意味ではありません。シェルの動作をユーザーの選択コマンドに対する合理的な期待から変更することは、驚くべきことであり、最終的には望ましくないように思えます。
トリプリー2016

@tripleee:人々がリレーや真空管を期待していた時期がありました。段ボールや紙テープに穴を開けることが期待されていました。人々は電卓や電話の代わりに計算尺を持っていました。私はあなたにとってこれが望ましいと思います。当時はあまり気にしませんでした。私は次が何であるかを見るのを楽しんでいます。
デビッドアンダーソン

8

拡張は、プログラムが実行される前にシェルによって実行されます。あなたのプログラムは、拡張が起こったかどうかについての手がかりを持っていません。

   set -o noglob

呼び出しシェルで拡張をオフにしますが、プログラムを呼び出す前にそれを行う必要があります。

別の方法は、あなたの議論を引用することです。

foo "*"

4
setoptはzsh固有のコマンドのようです。別のポスターが言ったように、bashの場合、set -o noglobワイルドカード拡張を無効にするために使用します。
Wirawan Purwanto 2016

現在修正されています。ありがとう
BrianAgnew18年

1

注意:マスクに一致する名前がない場合、bashは展開せずに引数をそのまま渡します!

証明(pa.pyは非常に単純なスクリプトであり、引数を出力するだけです):

 $ ls
f1.cc  f2.cc  pa.py
 $ ./pa.py *.cc
['./pa.py', 'f1.cc', 'f2.cc']
 $ ./pa.py *.cpp
['./pa.py', '*.cpp']

3
常にではない。set -o nullglobまたはshopt -s failglob、この動作は変化します(2つの非常に異なる方法で)。
チャールズダフィー2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.