ターミナル、シェル入門
今回のゴール
- ターミナルとシェルの基本的な操作方法や構文を理解する
- 環境変数やPATHなど、ターミナル上でコマンドを実行する上で必要な知識を得る
- Homebrew など、Macでターミナルを利用する際に便利なツールを知る
このスライドについて
このスライドの内容は、ターミナル (コマンドライン) を初めて使う方向けに記載したものです。
ターミナルやシェルの世界は奥が深いですが、ここでは最低限の知識に絞り、「必要な用語と概念を理解する」ことを重視しています。
より詳しく学びたい方は、シェルやシェルスクリプトの書籍・ドキュメントを参照してください。また、今はAIを通じて「こういう操作をzshで書くには?」などと聞けるので、細かいコマンドの操作方法などは必要に応じて覚える形で良いでしょう。
なお、今回紹介する内容は基本的に Mac の環境を想定していますが、Windows の場合でもWSLを利用する場合は多くの内容が該当するかと思います。
ターミナルとは
ターミナルとは、コマンド(命令文)を入力してPCを操作できるアプリで、Mac では「ターミナル.app」、Windows では「Windows Terminal」がこれにあたります。
ターミナルの画面は環境や設定によって異なりますが、このスライドでは以下のような形でターミナル上の入力、出力を記載します。
$ <ここにターミナルに入力したコマンドを書く>
<ここにコマンドの出力を書く>
例えば以下の場合、echo "Hello!" が入力したコマンドで、Hello! がコマンドの出力になります。
$ echo "Hello!"
Hello!
ターミナルとシェル
ターミナルを起動すると、中でシェルというプログラムが動いています。
- ターミナル: 画面(ウィンドウ)を提供するアプリ。コマンドラインとも呼ばれる
- シェル: 入力されたコマンドを解釈し、PCを操作するプログラム (ターミナルの中で利用されているアプリケーションの一つ、という認識で良い)
また、似たような用語として CLI (Command Line Interface) や CUI (Character User Interface) があり、これらはマウス等でPCを操作する GUI(Graphical User Interface)に対し、ターミナルやシェルを用いてPCを操作する方法のことを示します。例えば、「CLIツールである」というのは「ターミナル上で利用するツールである」という意味になります。
シェルの種類
シェルにはいくつかの種類があります。
- bash: Linux サーバーでよく使われる。昔からあるシェルのため書籍やWeb上の情報は多い
- zsh: Mac のデフォルトシェル。補完機能が豊富
- fish: 比較的新しいシェルで、色付き表示が充実している。構文が少し独特
このスライドでは、基本的には zsh での動作を前提とします (ただし、他のシェルでもほとんど動きます)
シェルにおけるパス
ターミナルで操作をする場合、ファイルやディレクトリの場所 (パス) を指定することが必要になります。
ターミナルを操作するとき、「現在、このディレクトリの中で操作している」という前提で行われます。コマンドでパスを指定するときは「現在のディレクトリのパス」が基準となり、現在のディレクトリのパスは pwd というコマンドで確認できます。また、cd <移動先のパス> というコマンドで現在のパスを移動することができます
$ pwd
/Users/urahiroshi
$ cd Documents # 現在のディレクトリ内の `Documents` というディレクトリに移動する
$ pwd
/Users/urahiroshi/Documents
絶対パスと相対パス
パスには絶対パスと相対パスの2種類があり、コマンド上でパスを指定する場合はどちらのパス指定方法も使うことができます。
相対パスの例: 現在のパスを基準としたパスを指定する (現在のパスが変われば対象が変わる)
$ cd Documents
絶対パスの例: / から始まるパスで、現在のパスに関わらず同じパスを指定できる
$ cd /Users/urahiroshi/Documents
基本的なコマンドの実行例 (ls)
ディレクトリ内のファイルやフォルダの一覧を表示する (ls もしくは ls <パス>)
# 現在のディレクトリの中身を表示
$ ls
Applications Desktop Downloads Movies Pictures s
bin Documents Library Music Public temp
# パスを指定して表示
$ ls Documents
report.txt work notes
コマンドはオプションを指定することで挙動を変えることができます。例えば、ls にたいして -l というオプションを指定すると、ファイルやフォルダの詳細情報を表示するようになります。
$ ls -l
drwxr-xr-x 5 user staff 160 3 17 10:00 Desktop
drwxr-xr-x 3 user staff 96 3 17 09:30 Documents
基本的なコマンドの実行例 (cat, cp)
ファイルの中身を表示する: cat <ファイルパス>
# readme.txt の中身を表示
$ cat readme.txt
ファイルをコピーする: cp <コピー元> <コピー先>
# ファイルをコピー
$ cp memo.txt memo_backup.txt
# `-r` オプションでディレクトリをコピーすることもできる
$ cp -r project project-backup
特別なパス表記
パスの中で特別な意味を持つ記号があります。
. => 現在のディレクトリ
.. => ひとつ上のディレクトリ
$ ls .
# `ls` と同じ。現在のディレクトリ (例: /Users/urahiroshi/Documents) の中身が表示される
$ ls ..
# 現在のディレクトリの親ディレクトリ (例: /Users/urahiroshi) の中身が表示される
$ ls ../Pictures
# 親ディレクトリから見て `Pictures` というパス (例: /Users/urahiroshi/Pictures) の中身を表示
ホームディレクトリ(~)
ホームディレクトリは、現在のユーザー用のディレクトリであり、ターミナルを開いたときに最初にいるパスです (例: /Users/urahiroshi)。 ~ というパスで省略して表記できます。
# ~ はホームディレクトリを表し、以下は `ls /Users/urahiroshi` と同じ意味になる
$ ls ~
# 以下は `ls /Users/urahiroshi/Documents` と同じ意味
$ ls ~/Documents
標準出力(STDOUT)とエラー出力(STDERR)
コマンドの実行結果は、標準出力やエラー出力として表示されます。
- 標準出力(STDOUT): コマンドが成功した場合の出力内容
- エラー出力(STDERR): エラーが発生した場合の出力内容
$ ls
file1.txt file2.txt
# エラー出力の例: 存在しないファイルを指定した場合はエラー出力になる
$ ls nofile.txt
ls: nofile.txt: No such file or directory
echo というコマンドで、標準出力に指定した文字を出力することもできます。
$ echo "hoge"
hoge
出力をファイルに書き出す(リダイレクト)
> や >> を使うと、標準出力やエラー出力をファイルに保存することができます。
# > で新規作成(既存ファイルは上書きされる)
$ echo "メモ" > memo.txt
# >> で追記(既存ファイルの末尾に追加される)
$ echo "追加のメモ" >> memo.txt
# エラー出力をファイルに書き出す(2> を使う)
$ ls nofile.txt 2> error.log
> の場合、標準出力のテキストからファイルを新規作成します。ファイルが存在する場合はファイルの内容がすべて置き換えられます。
>> も標準出力のテキストをファイルに書き込みますが、ファイルが存在する場合は現在の内容に追記します。
- エラー出力を書き出す場合は
2> や 2>> のように書きます。
やってみよう
ターミナルを立ち上げて、以下のような操作をしてみましょう
- 様々なディレクトリを移動して、
ls でディレクトリの中のファイルやディレクトリを見る
/tmp ディレクトリの中で hello! と書かれた temp.txt を作成する
temp.txt をコピーして temp2.txt を作る
cat で temp2.txt の中を確認する
sandbox.bio のようなWebサービスで、ブラウザからターミナル操作を試すこともできます。
これから、よく使うコマンドをいくつか紹介します
- ここでは、「コマンドの名前」と「どんな役割を持ったコマンドか」を理解していただくと良いです。
- コマンドの構文や詳細な使い方については、今の時点では覚える必要はありません (いざとなったらAIに聞くでも良いです)
コマンド紹介: mkdir, less
mkdir: ディレクトリを作成する
less: ファイルをスクロールしながら閲覧する(長いファイル向け。q で終了)
# ディレクトリを作成
$ mkdir new-project
# 長いファイルをスクロールして読む
$ less long-log-file.txt
コマンド紹介: rm, mv
rm: ファイルを削除する
mv: ファイルやディレクトリを移動する。名前変更もこのコマンドを使う
# ファイルを削除
$ rm old-file.txt
# ファイルを移動・リネーム
$ mv memo.txt backup/memo.txt
$ mv old-name.txt new-name.txt
注意: rm で削除したファイルはゴミ箱に入らず、元に戻せません。
コマンド紹介: grep, find
grep, find でファイルの中の文字列を検索したり、ファイル自体を検索することができます。 *.txt のようなワイルドカード指定と組み合わせて複数のファイルを同時に処理することもできます (ワイルドカード指定は他のコマンドでも使えます)
grep: ファイルや入力から文字列を検索する
find: 指定したディレクトリ以下でファイルを検索する
# ファイル内で "error" を含む行を表示
$ grep "error" log.txt
# カレント以下で .txt ファイルを検索
$ find . -name "*.txt"
コマンド紹介: head, tail
head, tail でファイルの一部だけ表示することができます。「長いファイルの最後だけ見る」といった場合に便利です。
head: ファイルの先頭の行を表示する
tail: ファイルの末尾の行を表示する
# 先頭10行を表示(デフォルト)
$ head log.txt
# 先頭5行だけ表示
$ head -n 5 log.txt
# 末尾10行を表示(デフォルト)
$ tail log.txt
# 末尾20行を表示
$ tail -n 20 log.txt
よく使うコマンド: ps, lsof, kill
ps: 実行中のプロセス一覧を表示する
lsof: 特定のファイルやポートを使っているプロセスを特定する
kill: プロセスを終了する
# プロセス一覧を表示(aux で全ユーザー・詳細表示)
$ ps aux
# 8000番ポートで起動しているプロセスを特定する
$ lsof -i :8000
# 指定したプロセスID(PID)のプロセスを終了する
$ kill 1234
これらのコマンドを使いこなすにはプロセスの概念を理解する必要があります。ここでは詳細は記載しませんが、うまく使いこなせば「問題を起こしているプロセスを確認し、強制終了させる」といった操作を行うことができます。
パイプ(|)で出力を別のコマンドに渡す
パイプ(|) を使うと、あるコマンドの標準出力を、別のコマンドの入力として渡せます。
# 実行中のプロセス一覧から "node" を含むものだけ抽出する
$ ps aux | grep node
urahiroshi 1234 0.1 0.5 node server.js
urahiroshi 5678 0.0 0.2 node watch.js
複数のコマンドをパイプでつなげることもできます。
# プロセス一覧から node を抽出し、件数を数える
$ ps aux | grep node | wc -l
3
Tab キーによる入力補完
Tab キーを押すと、コマンド名やファイルパスを自動で補完してくれます。
# ここで tab キーを押すと、 `ls Documents` のように補完してくれる
$ ls Doc
# 2回 tab キーを押すことで、複数候補がある場合に表示される
$ ls D
# => Desktop Documents Downloads などが表示される
処理を途中で止める: Ctrl+C
実行中のコマンドを途中で止めたい場合は Ctrl+C を押します。
# sleep コマンドは指定した秒数だけ待機する
$ sleep 1000
# (1000秒 = 約16分 待つことになる)
# Ctrl+C を押すと...
^C
# すぐにコマンドが中断される
ターミナルで「処理が終わらない!」と思ったら、まず Ctrl+C を試してみましょう。
コマンド履歴の検索: Ctrl+R
これまで自分が実行したコマンドはPC上に記録されており、history というコマンドで参照することができます。
# 最近実行したコマンドを見る
$ history | tail
また、↑ キーによって前に実行したコマンドを参照でき、Ctrl+R を押すと、過去に入力したコマンドを検索して再実行することができます。
# Ctrl+R を押すと...
(reverse-i-search)`':
# ここに文字を入力すると、履歴から一致するコマンドを検索
# 例: "ls" と入力 → 過去の ls コマンドが表示される
# Enter でそのコマンドを実行、Ctrl+C で検索をキャンセル
Mac で便利なコマンド: pbcopy, pbpaste, open
Mac でターミナルを利用する場合は以下のコマンドも便利です。
- pbcopy: 入力をクリップボードにコピーする (テキストをコピーする)
- pbpaste: クリップボードの内容 (コピーしたテキスト) を出力する
- open: ファイルやフォルダ、URL をデフォルトアプリで開く
# memo.txt ファイルの中身をコピーする (ターミナル以外でも使える)
$ cat memo.txt | pbcopy
# コピーしたテキストを temp.txt に書き込む
$ pbpaste > temp.txt
# HTMLファイルをブラウザで開く
$ open index.html
環境変数とPATH
次に、環境変数やPATHについて学んでいきます。以下のような内容が含まれます
- コマンドを実行する場合に利用する変数 (環境変数)
- まとまったコマンドをファイルに書いて実行する方法 (シェルスクリプト)
- スクリプトやコマンドがどうやって実行されるか (アクセス権限、PATH)
環境変数とは
環境変数は、シェル上でコマンドを実行する際に利用されるパラメータのようなものです。
自分で環境変数を定義することもできますが、最初から定義されている環境変数も多数あり、printenv コマンドですべての環境変数を参照できます。また、 $変数名 で環境変数の値を参照してコマンドに用いることができます。
$ printenv | grep HOME=
HOME=/Users/urahiroshi
$ echo "私の名前は $USER です"
私の名前は urahiroshi です
# $HOME=/Users/urahiroshi の場合、/Users/urahiroshi/Documents に移動
$ cd $HOME/Documents
シェルスクリプト
まとまったシェルの処理はシェルスクリプトとしてファイルに書くことができます。例えば以下のようなファイルを sleep.sh として保存して使うことができます。
(シェルスクリプトは慣例的に .sh の拡張子をつけることが多いです)
#!/bin/bash -eu
echo "3秒待ちます..."
sleep 3
echo "3秒待ちました!"
シェルスクリプトの書き方は複雑なので詳細は割愛しますが、興味がある方は調べてみてください。
シェルスクリプトの呼び出し方
sleep.sh にシェルスクリプトを保存した場合、そのシェルスクリプトは bash sleep.sh のように bash コマンドに渡すことで利用できます (bashの記法で書いたシェルスクリプトなので bash コマンドを使っていますが、zshの記法で書いたものなら zsh コマンドに渡せます)
さらに、個々のファイルには「読み取りができるか(読み取り権限があるか)」「書き込みができるか(書き込み権限があるか)」「実行ができるか(実行権限があるか)」という情報が入っており、chmod というコマンドで権限を更新できます。 chmod で実行権限をつけることで、ファイル名を呼ぶだけで実行できるようになります。
$ chmod +x sleep.sh
$ ./sleep.sh
(参考) 読み取り権限、書き込み権限、実行権限について
ls -l でファイルの権限を確認することができます。
r が読み取り権限、w が書き込み権限、x が実行権限を表し、すべての権限がある場合は rwx, ない場合は --- のように3文字で表します
- ファイルにはオーナーとなるユーザー、グループがあります。
ls -l の出力では、オーナー、オーナーグループ、それ以外のユーザーの3種類に対するアクセス権を順に表示します
- 例えば、
-rwxr-xr-x と表示される場合は rwx, r-x, r-x の3つのアクセス権の組み合わせの意味で、順にオーナーの権限 (rwx: 読み取り・書き込み・実行可能)、グループの権限 (r-x: 読み取りと実行は可能、書き込みは不可)、それ以外のユーザーの権限を表します。
$ ls -l sleep.sh
-rwxr-xr-x@ 1 urahiroshi staff 0 3 18 12:14 sleep.sh
コマンドはどこにあるか
例えば ls というコマンドはどうやって実行されているでしょうか?
実は、ls は /bin/ls という実行権限のあるファイルが本体であり、/bin/ls と直接パスを指定して呼び出すこともできます。
「コマンドが実際にどこにあるか」を確認するには、which というコマンドが利用できます。
$ which ls
/bin/ls
なお、特定のファイルではなく最初からシェルの機能として組み込まれているコマンドもあります (cd など)
$ which cd
cd: shell built-in command
PATH環境変数
では、/bin/ls ではなく ls だけでコマンドを呼び出せるのはなぜでしょうか?
シェルは、PATH という環境変数に登録されたディレクトリを参照し、PATHのディレクトリ上のファイルは、実行権限があればファイル名だけでコマンドとして呼び出せます。 ls だけで /bin/ls が呼び出せるのは、 /bin が PATHの中に入っているためです。
# PATH 環境変数には、ディレクトリのパスが `:` 区切りで入っている
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
逆に言えば、コマンドを呼び出せないとき、「PATHに入っていない」「実行権限がない」のどちらかが原因と言えます。
PATHが通っていないとき
対象のコマンドのディレクトリが PATH 環境変数に登録されていない (PATH が通っていない) 場合、コマンドを実行しようとしても見つからないといったエラーになります。
$ mycommand
zsh: command not found: mycommand
このような場合は、シェルの設定ファイル(~/.zshrc など)に PATH を書き換える処理を追記することで解決できます。
# ~/.zshrc に追記する例
export PATH="$HOME/.local/bin:$PATH"
# 設定を反映する
$ source ~/.zshrc
やってみよう
シェルスクリプトを作り、そのシェルスクリプトをどこからでもコマンドとして呼び出せるようにしてみましょう。
~/.local/bin ディレクトリを作成する
- 以下の内容で
~/.local/bin/hello を作る#!/bin/bash
echo Hello!
- ここで
hello や ~/.local/bin/hello を実行しても呼び出せず、bash ~/.local/bin/hello で呼び出せることを確認する
chmod コマンドで hello に実行権限をつけ、 ~/.local/bin/hello などで呼び出せることを確認する
やってみよう (続き)
~/.zshrc で $HOME/.local/bin をPATHに追加する (export PATH="$HOME/.local/bin:$PATH" を追記)
source ~/.zshrc で設定を読み込む
- どこからでも
hello で呼び出せるようになることを確認する
ターミナルやシェルに関連するツールの紹介
以降では、ターミナルでよく利用するツールとして、エディタ、パッケージマネージャ、gitなどのツールを紹介します。
- vim, nano
- Homebrew
- VSCode
- git
ターミナル上のエディタ: vim, nano
ターミナル上でテキストファイルを編集できるエディタがあります。Macの環境で最初から利用できるものは以下の2つになります。
nano: 初心者向けのシンプルなエディタです。
# nano でファイルを開く
$ nano memo.txt
# 画面下部に操作方法が表示される(^X = Ctrl+X で終了)
vim: 高機能なエディタですが、操作に慣れが必要です。
# vim でファイルを開く
$ vim memo.txt
# i を押すと入力モード、Esc で通常モード、:wq で保存して終了
VSCode とターミナル
Visual Studio Code (VSCode) は、ターミナルの機能も内蔵しており、以下のようにターミナルを表示して使うことができます。
表示方法:
- メニュー: 表示 → ターミナル
- ショートカット: Command + j (Windows の場合は Ctrl + j)
ターミナルパネルが下部に開き、プロジェクトのフォルダを開いた状態で作業ディレクトリが自動的にプロジェクトのルートになります。
Homebrew
Homebrew は Mac のターミナル上で使えるパッケージマネージャです。
Homebrew のインストール後、 brew コマンドによって様々なアプリやコマンドのインストールやバージョンの管理を簡単にできるようになります。
# Homebrew でパッケージをインストールする例
$ brew install git
$ brew install node
# インストール済みのパッケージ一覧を確認
$ brew list
Windows の場合は winget などのパッケージマネージャがあります。
Git をターミナルで使う
Git の操作は Visual Studio Code の GUI でもできますが、Gitは本来ターミナル上で操作することを想定したツールなので、ターミナルで直接利用することで様々な操作が可能になります。
# リポジトリの状態を確認
$ git status
# 現在のディレクトリ内の変更内容をステージングに追加
$ git add .
# コミットする
$ git commit -m "ヘッダーのデザインを修正"
# ログを確認(--oneline で1行表示、-5 で直近5件)
$ git log --oneline -5
やってみよう
以下のように、gitの操作をターミナル上でやってみましょう
~/temp/play-git ディレクトリを作り、そこに移動する
(以下の操作は play-git ディレクトリ内で行う)
git init によりgitリポジトリとして初期化する
memo.txt ファイルを作り、ファイルに何か書き込む (何でも良い)
git status により状態を確認し、 git add . により memo.txt をステージングする
git commit -m "<コミットメッセージ>" によりコミットする
git log によりコミットログを確認する
ターミナル・シェルのカスタマイズ(応用編)
ターミナル環境を自分好みにカスタマイズし、より使いやすくすることができます。ここでは用語だけ紹介するので、興味がある方は調べてみてください。
- ターミナルアプリを変える: iTerm2、Ghostty, cmux など高機能なターミナル
- ターミナルマルチプレクサ: tmux、zellij など(1つのターミナルで複数の画面を管理)
- プラグインを使う: oh-my-zsh などでシェルの機能を拡張
- alias を設定する: よく使うコマンドに短い別名をつける
# alias の例(~/.zshrc に記載)
alias ll="ls -la"
alias gs="git status"
まとめ
- ターミナルはコマンドでPCを操作する画面、シェルはコマンドを解釈するプログラム。CLIやCUIなどとも呼ばれる。
- パスは絶対パスと相対パスがあり、パスの指定には
.(現在のディレクトリ)、..(親ディレクトリ)、~(ホームディレクトリ)といった記号が使える
- コマンドの実行結果は STDOUT(標準出力) や STDERR(エラー出力) として表示され、
>, >>, 2> でファイルに書き出せる。また、パイプ(|) を使って別コマンドの入力として渡せる
- ターミナルの操作: Tab キー で補完、Ctrl+R で履歴検索、Ctrl+C で処理の中断
- 環境変数は
$変数名 で参照。PATH に登録されたディレクトリ内の(実行権限がある) コマンドは名前を呼び出すだけで実行できる
- Homebrew でツールのインストールができる
さらに学ぶには
ターミナルの操作について、より深く知りたいところはAIに聞きながら調べてみるのはもちろん、「bash」「zsh」「シェルスクリプト」「コマンドライン」などに関する書籍でより深く学ぶこともできます。