CSセミナー007 bash入門

# 概要

第７回では、Windows Subsystem for Linux(Ubuntu)の基本操作を学ぶために、そのデフォルトのシェルであるbashについて解説します。

# Ubuntuを立ち上げる

Microsoft StoreからUbuntuをインストールされましたでしょうか？Ubuntuを立ち上げるためには、Cortanaにubuntuと入力して、Ubuntuと記載のあるアプリを選択します。
![001.png](https://qiita-image-store.s3.amazonaws.com/0/64229/349b14b7-b804-b1ce-524b-049cd037827c.png)

すると、コマンドプロンプトのような画面が表示されます。
![002.png](https://qiita-image-store.s3.amazonaws.com/0/64229/2f2b473b-c48d-deeb-3d71-1b88881896a2.png)
この画面では、実際には**bash**というプログラムが動いています。Linuxではキーボード入力によってコンピュータを操作するプログラムのことを**シェル**と言います。bashはUbuntuがデフォルトで設定しているシェルです。

# ディレクトリ

エクスプローラは、とあるフォルダを表示しています。
![003.png](https://qiita-image-store.s3.amazonaws.com/0/64229/82112a0d-bb01-76f4-ad72-d24c412a14b7.png)
この画面は、デスクトップを表示しています。ところでWindowsのフォルダは一般的には**ディレクトリ**(directory)と言います。bashも、とあるディレクトリを参照しています。bashが参照しているディレクトリのことを**カレントディレクトリ**(current directory)と言います。

ディレクトリ(directory)をOxford Directoryで検索すると以下のような定義が出てきます。
> A book or website listing individuals or organizations alphabetically or thematically with details such as names, addresses, and telephone numbers.

用例としては、company directoryが社員名簿、telephone directoryが電話帳といった感じです。

カレント(current)は、形容詞としては「現在の」、名詞としては「流れ、傾向、電流」という意味があります。したがってカレントディレクトリとは「現在のディレクトリ」という意味です。

カレントディレクトリを表示するには`pwd`コマンドを入力します。

```
user1@tamuken8:~$ pwd
/home/user1
```

ここで、user1は私のユーザー名であり、tamuken8はマシン名です。

次に、WindowsのCドライブのルートディレクトリに移動します。Windowsでいう`C:¥`のことです。

```
user1@tamuken8:~$ cd /mnt/c
user1@tamuken8:/mnt/c$ pwd
/mnt/c
```

`cd`コマンドはカレントディレクトリを変更します。`/`はLinuxのファイルシステムのルートディレクトリです。ルート(root)とは「木の根」のことであり、ルートディレクトリとは親のいないディレクトリのことです。Windowsのファイルシステムにおいてルートディレクトリはドライブレターの数だけ存在しますが、Linuxのファイルシステムでは１つです。

WSLでは`/mnt`ディレクトリの下に、ドライブレターの名前のディレクトリがあります。これがWindowsのルートディレクトリになります。したがって、`D:¥`のディレクトリパスは`/mnt/d`となります。

# ファイルを検索する

さて、Linuxでファイルを検索するにはどうすればいいのでしょうか。ブラウザに「Linux ファイルを検索」と入力して検索してみましょう。`find`コマンドを使うと書いてあったのではないかと思います。さて、`find`と入力してみましょう。
![001.gif](https://qiita-image-store.s3.amazonaws.com/0/64229/55e6089d-b175-6ee9-7209-d49cefdf909d.gif)
`find`コマンドは引数無しで呼び出すとカレントディレクトリと、そのサブディレクトリのすべてのファイルを表示します。しかし`C:¥`の中にはたくさんのファイルが入っているのでこのコマンドが終了するのにとても時間がかかります。コマンドを途中で強制終了させるためには[Ctrl + C]キーを入力します。

ここで、`grep`ファイルを併用してみます。例えば、`C:¥`以下にある`kernel32.dll`というファイルを検索してみます。
![002.gif](https://qiita-image-store.s3.amazonaws.com/0/64229/aecc28c8-0a6a-01e0-7c12-3ec58a70bfd0.gif)
このとき、`find`コマンドは大量の`Permission denied`というエラーメッセージを出力します。Windowsにはユーザーがアクセスできないファイルやディレクトリが多数存在しています。さて、`find`コマンドの簡易ヘルプを見るために`find --help`と入力してみます。

```
user1@tamuken8:/mnt/c$ find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D debugopts] [path...] [expression]

default path is the current directory; default expression is -print
expression may consist of: operators, options, tests, and actions:
operators (decreasing precedence; -and is implicit where no others are given):
      ( EXPR )   ! EXPR   -not EXPR   EXPR1 -a EXPR2   EXPR1 -and EXPR2
      EXPR1 -o EXPR2   EXPR1 -or EXPR2   EXPR1 , EXPR2
positional options (always true): -daystart -follow -regextype

normal options (always true, specified before other expressions):
      -depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf
      --version -xdev -ignore_readdir_race -noignore_readdir_race
tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N
      -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME
      -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN
      -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE
      -nouser -nogroup -path PATTERN -perm [-/]MODE -regex PATTERN
      -readable -writable -executable
      -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N
      -used N -user NAME -xtype [bcdpfls]      -context CONTEXT

actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print
      -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit
      -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;
      -execdir COMMAND ; -execdir COMMAND {} + -okdir COMMAND ;

Valid arguments for -D:
exec, help, opt, rates, search, stat, time, tree
Use '-D help' for a description of the options, or see find(1)

Please see also the documentation at http://www.gnu.org/software/findutils/.
You can report (and track progress on fixing) bugs in the "find"
program via the GNU findutils bug-reporting page at
https://savannah.gnu.org/bugs/?group=findutils or, if
you have no web access, by sending email to <bug-findutils@gnu.org>.
```

たいていの場合、この簡易ヘルプを見れば分かるのですが、分かりづらいですね。ブラウザに「find Permission Denied」と入力して検索してみましょう。だいたいこのように入力することで解決しているようです。
![003.gif](https://qiita-image-store.s3.amazonaws.com/0/64229/bac7fac5-60b1-7bc9-a4c5-bf6b4130f38c.gif)
`find 2> /dev/null | grep kernel32.dll'と入力したのですが、これの`2> /dev/null`というのは`find`コマンドの標準エラー出力をファイル`/dev/null`にリダイレクトするという意味です。デフォルトでは標準出力と標準エラー出力の２つがコンソールに出力されますが、`2> /dev/null`と入力することによって標準エラー出力の出力を抑制しています。Linuxで`/dev/null`というファイルがどういう意味を持っているのかを検索してみましょう。

[/dev/null - Wikipedia](https://ja.wikipedia.org/wiki//dev/null)

Wikipediaでもいいのですが、Linuxのマニュアルを読みたいところですね。「manual /dev/null」で検索すると「null(4)」と書いてあるページが散見されます。この、`(4)`や`(3)`などがついているようなページは`man`コマンドで見ることができる可能性が高いので、`man null`と入力してみます。
![004.png](https://qiita-image-store.s3.amazonaws.com/0/64229/7f994703-c30d-380f-80c8-b2de36e4193b.png)
`/dev/null`のマニュアルページが表示されました。スペシャルファイル`/dev/null`または`dev/zero`に書いたデータは破棄されます、とあります。ちょっと分かりづらいですがそういうものなのだと覚えておいてください。このマニュアルページは`q`ボタンを押すと終了します。

# ホームディレクトリ

さて、今はカレントディレクトリが`/mnt/c`になっているはずです。bash起動時のディレクトリは`/home/user1`(私の場合)でしたが、このディレクトリのことを**ホームディレクトリ**(home directory)と言います。それではホームディレクトリに戻ってみましょう。

```
user1@tamuken8:/mnt/c$ pwd
/mnt/c
user1@tamuken8:/mnt/c$ cd ~
user1@tamuken8:~$ pwd
/home/user1
```

`cd ~`と入力するとホームディレクトリに戻ります。bashでは、`~`(チルダ)はホームディレクトリを表します。

# `echo`コマンド

`echo`コマンドは標準出力に`echo`コマンドの引数を出力します。`ABC`を出力してみます。

```
user1@tamuken8:~$ echo "ABC"
ABC
```

次の３行の出力をさせることを考えます。

```
くいなちゃん６さい
Kuin Language
Windows
```

これを`echo`コマンドで行うには、文字列記述の中で改行してやります。
![004.gif](https://qiita-image-store.s3.amazonaws.com/0/64229/fb79f632-7b09-1c3d-b2e4-3a26d54e334f.gif)

# `grep`コマンド

さて、`grep`コマンドは与えられた標準入力かファイルの中でパターンにマッチした行を出力するコマンドです。先ほど、`find | grep kernel32.dll`と入力しましたが、この意味は、「`find`コマンドの標準出力を`grep`の標準入力に渡して`kernel32.dll`というパターンにマッチした行を標準出力に出力する」という意味です。`|`(バーティカルライン)はパイプというOSの機能を使うための記述です。今度は`echo`と`grep`を組み合わせてみましょう。

```
user1@tamuken8:~$ echo "ABC" | grep "ABC"
ABC
user1@tamuken8:~$ echo "ABCDEF" | grep "BCDE"
ABCDEF
user1@tamuken8:~$ echo "" | grep "ABC"
user1@tamuken8:~$ echo "ABC" | grep "くいなちゃん"
user1@tamuken8:~$ echo "くいなちゃん６さい" | grep "くいなちゃん６さい"
くいなちゃん６さい
user1@tamuken8:~$ echo "くいなちゃん" | grep "くいなちゃん６さい"
user1@tamuken8:~$ echo "くいなちゃん６さい" | grep "くいなちゃん"
くいなちゃん６さい
user1@tamuken8:~$ echo "くいなちゃん６さい" | grep "６さい"
くいなちゃん６さい
```

この挙動はどことなく正規言語に似ているように思いませんか？ただし正規言語では完全一致をさせていましたが、`grep`の正規表現では部分一致のパターンマッチを行います。完全一致を行うにはパターンを`^`と`$`で囲みます。

```
user1@tamuken8:~$ echo "くいなちゃん" | grep "^くいなちゃん$"
くいなちゃん
user1@tamuken8:~$ echo "くいなちゃん６さい" | grep "^くいなちゃん$"
user1@tamuken8:~$ echo "おはようくいなちゃん" | grep "^くいなちゃん$"
```

前方一致を行うにはパターンの後ろに`$`を書きます。

```
user1@tamuken8:~$ echo "くいなちゃん" | grep "くいなちゃん$"
くいなちゃん
user1@tamuken8:~$ echo "くいなちゃん６さい" | grep "くいなちゃん$"
user1@tamuken8:~$ echo "おはようくいなちゃん" | grep "くいなちゃん$"
おはようくいなちゃん
```

後方一致を行うにはパターンの前に`^`を書きます。

```
user1@tamuken8:~$ echo "くいなちゃん" | grep "^くいなちゃん"
くいなちゃん
user1@tamuken8:~$ echo "くいなちゃん６さい" | grep "^くいなちゃん"
くいなちゃん６さい
user1@tamuken8:~$ echo "おはようくいなちゃん" | grep "^くいなちゃん"
```

# `exit`コマンド

bashを終了させるには`exit`と入力します。

# まとめ

今回はbashの使用方法について簡単に学びました。