第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コマンドによって解釈してもらわねばならないわけですね。