【Mac/Linux】zshで *(メタ文字/ワイルドカード)を展開する方法

本記事は zsh で*を展開する方法について解説しています.

背景

bash や sh などのシェルではファイルを一括で処理したいとき,以下のようなスクリプトで対応できます.


#!/bin/bash

files="./*.txt"
for file in ${files}; do
    echo ${file}
done

上記のスクリプトをsample.shとして保存し,以下のようなディレクトリで実行した結果を見てみましょう.

ディレクトリ構造

.
├── 001.txt
├── 002.txt
├── 003.txt
└── sample.sh

結果

./001.txt
./002.txt
./003.txt

for文で一つずつ処理される際に*.txtが展開されるため,指定したディレクトリ内の*.txtファイルに対して任意の操作ができます.
今回の例ではカレントディレクトリ内の*.txtファイルパスがechoで表示されています.

シェルが zsh ではうまくいかない

ここでシェルをzshにする1*.txtの展開がうまくいかず以下のような結果になります.


#!/bin/zsh

files="./*.txt"
for file in ${files}; do
    echo ${file}
done
./*.txt

結果を見ると*.txtファイルとして認識されており,意図する挙動ではないですね・・・

対応策

zshではGLOB_SUBSTというオプションを有効にしないと*などが展開されません.

有効にする方法は以下の3つがあります.

  • 部分的に有効化
  • シェルスクリプト単位で有効化
  • .zshenvファイル(設定ファイル)で全体に有効化

順に見ていきましょう.

部分的に有効化

~オプションを変数につけることで部分的にGLOB_SUBSTを有効化することができます.
具体的には以下のように記載します.


#!/bin/zsh

files="./*.txt"
for file in ${~files}; do  # filesの前に ~オプションを付与
    echo ${file}
done
./001.txt
./002.txt
./003.txt

*.txtが展開され,意図した挙動となりました!

シェルスクリプト単位で有効化

GLOB_SUBSTを有効にしたいシェルスクリプトに以下の内容を記載します.

  • setopt GLOB_SUBST

#!/bin/zsh

setopt GLOB_SUBST  # 追記

files="./*.txt"
for file in ${files}; do
    echo ${file}
done
./001.txt
./002.txt
./003.txt

シェルスクリプト全体でGLOB_SUBSTが有効になるため~オプションを付けなくても bash や sh と同一の記載で展開されるようになります.

.zshenvファイル(設定ファイル)で全体に有効化

最後に.zshenv2に追記する方法です.
.zshenvに以下の内容を追記して有効化すれば,永続的な設定が全体に適用されます.

  • setopt GLOB_SUBST

有効化のコマンド3は以下です.
(成功しても何も表示されません)


echo setopt GLOB_SUBST >> ~/.zshenv && source ~/.zshenv

上記のコマンドを実行後は bash や sh と同じように記載することができます.


#!/bin/zsh

files="./*.txt"
for file in ${files}; do
    echo ${file}
done
./001.txt
./002.txt
./003.txt

ひとこと

bash と zsh の差は色々とありますね.
どちらでもいい感じに書けるようになりたい・・・


  1. シバン(#!/bin/zsh)で指定しています. 

  2. .zshenvというファイルはログイン/インタラクティブ/シェルスクリプトで常に使用する設定を定義しています. 

  3. このコマンドではホームディレクトリの.zshenvファイルにsetopt GLOB_SUBSTを追記し,それを有効化(source)しています.なお,ホームディレクトリに.zshenvファイルが存在していない場合は,.zshenvを作成してから追記してくれます.