スクリプトを書く

INPUT · スライド

`#!` と実行の印

01 / 08

3行打つのが面倒になったら

毎日こんなことをしているとするよ。

~ $ df -h > kiroku.txt~ $ du -sk * >> kiroku.txt~ $ date >> kiroku.txt

3行打つのは、正直めんどうでしょう。しかも順番をまちがえたり、1行忘れたりするよね。

こういうときはこう考えるんだ。

> 手順をファイルに書いて、名前で呼ぶ

書いたファイルをスクリプトと呼ぶよ。あなたはもう1つ見ているんだ。章10で ~/bin/aisatsu の中身を見たでしょう。

#!/bin/shecho konnichiwa

これがスクリプトだよ。たった2行だね。

この章でやることは、実はもう半分できているんだ。

コマンドを打てる       ← できるファイルに書ける       ← できる(echo と >>)実行の印を付けられる   ← できる(chmod +x)

章6と章10でやったことの組み合わせなんだよ。あとは1行目の #! を覚えるだけだね。

02 / 08

作って、印を付けて、呼ぶ

手順は3つだよ。

~ $ echo '#!/bin/sh' > shirabe.sh~ $ echo 'pwd' >> shirabe.sh~ $ chmod +x shirabe.sh~ $ ./shirabe.sh/home/manabiya

動いたね! 順に見ていくよ。

1. 中身を書く

echo '#!/bin/sh' > shirabe.sh    1行目echo 'pwd' >> shirabe.sh         2行目を足す

> で始めて >> で足すでしょう。章4でやった区別と、章10の .profile と同じだね。

2. 実行の印を付ける

chmod +x shirabe.sh

章6でやった x の印だよ。これが無いと動かないんだ。

3. ./ を付けて呼ぶ

./shirabe.sh

./ は「いまいる場所の」という意味だったね。章10の2本目で「.PATH に入っていない」とやったから、付けないと見つからないんだ。

書く → 印 → 呼ぶ。この3つを覚えれば、もうスクリプトが書けるよ。

03 / 08

#! は「これで動かして」の指定

1行目のこれは何だろうね。

#!/bin/sh

このファイルを動かす道具の指定だよ。「/bin/sh に読ませてね」という意味なんだ。

読み方はシバンと呼ばれるよ。#! をくっつけた呼び名だね。

正体を見る面白い実験があるよ。sh の代わりに cat を書いてみるんだ。

#!/bin/catkore ga deru

動かすとこうなるよ。

~ $ ./s.sh#!/bin/catkore ga deru

自分自身が出てきたでしょう。つまりこう動いているんだ。

./s.sh  ↓ 1行目を読む → /bin/cat を使えと書いてある/bin/cat s.sh

#! のうしろに書いた道具に、自分を渡しているだけなんだね。仕組みが分かると怖くないでしょう。

だから他の言葉でも同じ形になるよ。

#!/bin/sh          シェルスクリプト#!/usr/bin/python  Python#!/usr/bin/node    JavaScript

1行目を変えれば、中身の言葉が変わるんだ。

04 / 08

# なのに効くのはなぜ?

不思議に思ったかな。# から先はコメントで無視されるはずでしょう。

#!/bin/sh      ← # で始まっている

そのとおりで、シェルはこの行を無視しているんだ。読んでいるのは別の人だよ。

1. Linux(カーネル)が 1行目を見る  →  #! だ! /bin/sh を使おう2. /bin/sh がファイルを読む         →  1行目は # なので無視

読む人が2人いるんだね。だから「コメントなのに効く」という不思議な形になっているんだ。うまい仕掛けでしょう。

この仕掛けのおかげで、#! が無くても動くよ。

echo pwd > s.shchmod +x s.sh./s.sh          → 動く

シェルが「たぶんシェルスクリプトだろう」と面倒を見てくれるんだ。

でも必ず書いてね。理由は2つあるよ。

1. どの言葉で書いたか、読む人に分かる2. 別のシェルの人が動かしても、同じに動く

1行目の1行が、あとの混乱をぜんぶ防いでくれるんだ。

05 / 08

2つのエラーの読み分け

ここで出るエラーは2種類だよ。両方見ておこうね。

印を忘れたとき

~ $ ./s.sh-sh: ./s.sh: Permission denied

chmod +x s.sh を忘れているんだ。「許されていない」と言っているね。

./ を忘れたとき

~ $ s.sh-sh: s.sh: not found

ファイルは目の前にあるのに「無い」と言われるでしょう。これはPATH の中を探して見つからなかったという意味だよ。章10の2本目でやったね。

読み分けの表にしておくね。

出たもの足りないもの
Permission denied実行の印(chmod +x
not found./(または PATH

もう1つ、たちの悪いのがあるよ。

~ $ ./s.sh-sh: ./s.sh: not found

./ を付けたのに not found だって? これは#! のうしろの道具が見つからないときなんだ。

#!/bin/shh      ← 綴りまちがい

「無い」と言われているのはスクリプトではなく、道具のほうなんだよ。こういうときは1行目を疑ってね。

06 / 08

sh s.sh でも動く

印を付けずに動かす手もあるよ。

~ $ sh s.sh

sh に渡して読ませるんだ。この形なら chmod +x./ も要らないよ。

2つの形を比べておこうね。

./s.sh      自分で動くファイルとして呼ぶsh s.sh     sh に読ませる

どちらも結果は同じだけれど、意味が違うんだ。

./s.sh    「これは道具です」sh s.sh   「これは sh に読ませる文です」

使い分けはこうだよ。

人に渡す・毎日使う   →  印を付けて ./ で呼ぶちょっと試すだけ     →  sh s.sh で済ます

そして章10でやったあの区別も、ここでまた出てくるよ。

./s.sh       子シェルで動く. ./s.sh     今のシェルで動く

ドット1つの . を使うと、今のシェルで読むんだったね。設定を入れるスクリプトだけこの形にするんだ。

呼び方が4つあるけれど、ふだん使うのは ./s.sh だけだよ。

07 / 08

~/bin に置けば名前だけで呼べる

./ を付けるのが面倒になったら、章10の設定を思い出してね。

PATH="$PATH:$HOME/bin"

これを .profile に書いておくと、~/bin の中のものは名前だけで呼べるんだ。

~ $ mv shirabe.sh ~/bin/shirabe~ $ shirabe/home/manabiya

./.sh も要らなくなったでしょう。自分専用のコマンドができたんだ。

拡張子について言っておくね。

shirabe.sh    .sh があってもよいshirabe       無くてもよい

Linux は拡張子で動きを決めていないんだ。決めているのは #! と実行の印だからね。/bin の中を見ても、ls.sh なんて名前は無いでしょう。

手元で試すもの   s.sh のように .sh を付けると分かりやすい道具にしたもの   拡張子なしのほうが打ちやすい

どちらでもいいけれど、道具になったら拡張子を外すのがきれいだよ。あなたが打っている lscat と同じ形になるからね。

08 / 08

さあ、打ってみよう

この回で使う形をまとめておくね。

echo '#!/bin/sh' > s.sh     1行目を書くecho 'pwd' >> s.sh          続きを足すchmod +x s.sh               実行の印./s.sh                      呼ぶsh s.sh                     印なしで試すcat s.sh                    中身を確かめる

書くのは echo>> でいいよ。vi は章13でやるので、それまではこの形で足していってね。

そして、この回でいちばん大事なことを言うよ。

> スクリプトは、あなたが打ったコマンドをそのまま並べたもの

新しい書き方を覚える必要は無いんだ。今日まで打ってきたものを、上から順に書くだけだよ。

打てる  →  書ける  →  呼べる

この章の残りでやるのは「もっと賢くする」ことだよ。

次の回   外から値を渡す($1)その次   条件で分ける(if)その次   繰り返す(for / while)

でも土台は今日の3行だけなんだ。では作ってみよう。