本記事は 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 の差は色々とありますね.
どちらでもいい感じに書けるようになりたい・・・