第110回 クォートとパス名展開

*(アスタリスク)を囲うか? 囲わないか?

bashでコマンドを打つときに *(アスタリスク)を使う場面に出くわすことは多いと思います。

find / -name '*.txt'

とするとき、
「あれ? クォートいったけ? いらなかったけ?」
「この*(アスタリスク)はbashが展開する? findが展開する??
(たしか、クォートしなかった場合は、bashが展開したような....)」
となってしまいました。


この * をクォートで囲むべきなのか
はたまたダブルクォートで囲むべきなのか
いやいやクォートせずに使うべきなのか



曖昧な理解をやめるために調べてみました。

シングルクォートとダブルクォートの違いは?

http://www.linux.or.jp/JM/html/GNU_bash/man1/bash.1.html
こちらを参考に、以下引用を交えて調べていった結果を書きたいと思います。
(一部省略して引用しています)


引用:

クォートの方法には、 
エスケープ文字(escape character), シングルクォート、ダブルクォート
の 3 種類があります。 
ダブルクォートで文字を囲むと
クォート内部の全ての文字は文字としての値を保持しますが、
$, `, \ は例外となります。

なるほど
ダブルクォートは $, `, \が例外になるわけか。
ということは、*のみを使う場面ではシングルクォートを使っておくのがよいかもしれない。

パス名展開

引用:

展開はコマンドラインが単語へ分割された後に (コマンドライン上で) 行われます。
行われる展開は 7 種類あります:
  ブレースの展開 (brace expansion),
  チルダの展開 (tilde expansion),
  パラメータと変数の展開 (parameter and variable expansion),
  コマンド置換 (command substitution),
  算術式展開 (arithmetic expansion),
  単語の分割 (word splitting), 
  パス名の展開 (pathname expansion)。 

なるほどぉ
一口に展開といっても、7種類も展開があったのか、今回気になっているのは、
「パス名の展開」にあたるやつだ。



引用:

-f オプションが指定されていなければ、
単語分割を行った後に bash はそれぞれの単語が *, ?, [ を含んでいるかどうか調べます。
これらの文字のいずれかが見つかると、その単語は パターン と見なされ、
パターンにマッチするファイル名をアルファベット順にソートしたリストに置換されます。

なるほど
やはり、クォートしないとbashが展開しているのですね。


いま、以下のようなファイルがあるディレクトリで、echoを使ってみましょう。

$ ls
f10	f11	f7	f8	f9


クォートなし

$ echo *
f10 f11 f7 f8 f9

なるほど。展開されています。


クォートあり

$ echo '*'
*

なるほど。展開されていません。


findに渡すとき

ではfindで試してみましょう。


クォートなし

$ find . -name f*
find: f11: unknown option

これではfindに渡るまえにbashで展開されてしまい、f11なんていうオプションはないと怒られてしまいました。


クォートあり

$ find . -name 'f*'
./f10
./f11
./f7
./f8
./f9

うまくいきました。
findコマンドに'f*'という文字列として渡してあげて、その'f*'を、findコマンドによって解釈してもらわねばならないわけですね。