KDE BLOG

Webデザインやコーディングについて書いています

unixコマンドの基本的まとめ

<目次>

UNIXコマンド入門 [一般ユーザー編] (全24回) - プログラミングならドットインストールを一通りやり終えたのでメモ + 調べたことまとめ。

基本編

コマンド 説明
pwd 現在のディレクトリを表示(print working directory
clear または ctrl + l 画面クリア

ディレクトリ間の移動

コマンド 説明
cd ディレクトリの移動
cd ..1つ上の階層に移動
cd -直前のディレクトリに移動
cdホームディレクトリに移動
clear または ctrl + l 画面クリア

ディレクトリの操作

コマンド 説明
mkdir ディレクトリの作成
mkdir -p hoge/fugahogeディレクトリがなくてもfugaディレクトリが作成できる(parents
ls ファイル、ディレクトリの表示(list
ls -a隠しファイルも含めて表示
ls -lパーミッション権限など詳細を表示
cp コピー
cp -r再帰的(recursive)にコピー
mv ファイル、ディレクトリの移動
※同ディレクトリ内で使うと名前の変更になる
例)mv hoge.txt hoge2.txt
rmdir ディレクトリの削除
rm ファイルやディレクトリの削除
rm -rディレクトリを削除(再帰的:recursive
rm -rfディレクトリごと警告なしで削除

ファイルの操作

コマンド 説明
cat ファイルの中身をすべて表示(画面に収まらない場合、上部は見切れてスクロールさせる必要あり)
less ファイルの中身を画面内に収まる範囲で表示
スペースキーorctrl + F一画面先に移動(forward)、ctrl + B一画面前(back)に戻る
g先頭に移動
G末尾に移動
/検索語検索語で検索
 n次の箇所に移動(next
 N前の箇所に戻る
q終了(quit

bashの便利機能

キー操作 説明
tabキー 補完
ctrl + c キャンセル、中止
or 履歴表示
ctrl + r 履歴検索
ctrl + rで再検索

コマンドの履歴

コマンド 説明
history コマンド履歴表示
!履歴番号 そのコマンドを実行
!! 1つ前のコマンド実行
!-n n個前のコマンド実行
!$ 直前のコマンドに渡した最後の文字列
例)mkdir hoge/fuga cd !$-> hoge/fugaが!&の引数に渡される
!検索語 検索語から始まる直近のコマンドの実行
!検索語:p 検索語から始まる直近のコマンドの確認

コマンドの詳細(ヘルプ)

コマンド 説明
〇〇 --help ヘルプ表示
man 〇〇 コマンド〇〇の詳細を表示(less表示)

シンボリックリンクの作成

コマンド 説明
ln -s {元のディレクトリパス} {シンボリックリンク名} シンボリックリンク作成
例)ln -s path/to/hoge fuga
unlink {シンボリックリンク名} シンボリックリンク削除
例)unlink fuga

ユーザー、グループの確認

ls -lで詳細表示

drwxrwxr-x. 3 vagrant vagrant 4096  1月 20 11:50 2018 config
lrwxrwxrwx. 1 vagrant vagrant   26  1月 20 12:06 2018 dbconfig -> config/production/database
-rw-rw-r--. 1 vagrant vagrant 1342  1月 20 11:07 2018 hello.txt

▼表示内容

  1. 1文字目がタイプを表す。
  2. d ディレクト
  3. l シンボリックリンク
  4. - ファイル
  5. パーミッションに関する情報。
  6. リンク数
  7. このファイルを所有しているユーザーとグループ
  8. ファイルサイズ
  9. 最終更新日
  10. ファイル名

ユーザーの確認

cat /etc/passwdでユーザー一覧表示

(略)
vagrant:x:500:500:vagrant:/home/vagrant:/bin/bash
(略)

▼表示内容

  1. ユーザー名
  2. x パスワードが表示されている意味
  3. ユーザーのID
  4. メインで所属しているグループのID
  5. ユーザーに付けられたコメント
  6. homeディレクトリの位置
  7. シェルとして使うコマンド

グループの確認

cat /etc/group でグループ一覧表示

(略)
vagrant:x:500:vagrant
(略)

▼表示内容

  1. グループ名
  2. x パスワードが表示されている意味
  3. グループのID
  4. グループに所属しているユーザー名

groups コマンドでも自分が所属しているグループ名を確認できる。

パーミッションについて

パーミッションの見方

権限 説明
r (read) 読み込み可
w (write) 書き込み可
x (execute) 実行可

ディレクトリに関しては実行するものではないため、xが付いていたらそのディレクトリを開くことができるという意味になる。

図の場合、
vagrantユーザーは「読み・書き・実行」が可能。
vagrantグループに属するユーザーは「読み・書き」が可能。
その他ユーザーは「読み」が可能。

パーミッションの変更

chmod {パーミッション変更} {対象ファイル} で変更

# グループ(g)の実行を許可
chmod g+x sample.txt

# 所有ユーザー(u)とその他ユーザー(o)の書き込みを不認可
chmod uo-w sample.txt

# すべてのユーザー(a)の読み・書きを許可。実行を不認可
chmod a+rw-x sample.txt

パーミッションを数値で表現

権限 2進数
r 4
w 2
x 1

ステータスは上記2進数の合計値で表す。

# すべてのユーザーに「読み・書き・実行」許可
chmod 777 sample.txt

# 所有ユーザー「読み・書き・実行」許可
# グループユーザー「読み・書き」許可
# その他ユーザー「読み」許可
chmod 761 sample.txt

# すべてのユーザー「読み・書き」を許可
# グループユーザー「読み・実行」許可
# その他ユーザー 許可なし
chmod 650 sample.txt

コマンドの作成

「Hello」と書かれたテキストファイルを現在のディレクトリに出力するコマンドhelloを作る

作成手順

  1. 既にそのコマンドがないか確認する
type hello
bash: type: hello: not found
  1. コマンドファイルの作成
touch hello
#!/bin/bash
echo "Hello" > ./Hello.txt
  1. そのままでは実行できないので権限を追加
chmod u+x hello
  1. 実行(ディレクトリを指定する必要あり)
./hello

PATHを通す(環境変数の操作)

上記で作成したhelloコマンドは、./helloディレクトリを指定する必要があった。
これはUNIXでは、コマンドを検索するディレクトリが決められており、そのディレクトリ外にあるコマンドを実行する場合は、そのファイルがどこにあるか指定しなければいけないルールがあるため。

その「コマンドを検索するディレクトリ」は環境変数というもののひとつに保存されておりecho $PATHもしくはprintenv PATHで確認できる。

echo $PATH
/home/vagrant/.pyenv/plugins/pyenv-virtualenv/shims:/home/vagrant/.pyenv/shims:...(略)

ディレクトリは:で区切られていて、コマンドを実行する際はこれらディレクトリを最初から探索していく。

なお、$PATH以外のすべての環境変数を見るにはprintenvを実行する。

環境変数に追加

helloでコマンドを実行させるには、上記を踏まえて、環境変数$PATHにコマンドのディレクトリを追加すればよい。

# コマンドのディレクトリを確認
pwd
/home/vagrant/unix_lessons/myapp

# 上記ディレクリをPATHの先頭に追加
# ※ $PATHには追加直前のPATH情報が入っている
# ※ 「:」で区切るのを忘れない
export PATH=/home/vagrant/unix_lessons/myapp:$PATH

# 正しく追加されたか確認する
echo $PATH
/home/vagrant/unix_lessons/myapp:/home/vagrant/.pyenv/plugins/pyenv-virtualenv/shims:/home/vagrant/.pyenv/shims:...(略)

これでhelloでコマンド実行可能となる。
このように特定のディレクトリをPATHに追加することを「PATHを通す」と呼ぶ。

どこのディレクトリから呼び出されているか確認する

whichコマンドを使うことで確認可能

which hello
~/unix_lessons/myapp/hello

新たな環境変数の作成、削除

上記では既存のPATHに追加したが、新規で追加するのもほぼ同じ。

# HOGEという環境変数にfugaを追加する
export HOGE=fuga

# 保存されたか確認する
echo $HOGE
fuga

削除をするにはunsetを使う

unset HOGE

# 確認すると何も表示されない = 環境変数がない
echo $HOGE

設定した環境変数はログアウトすると消える

通常は、ログアウトすると設定した環境変数は消えてしまう。
これをログアウトしても設定されている状態にするには、~.bash_profile~.bashrcに設定する。
結論をいうと ~.bash_profileに設定が望ましい。

その理由は下記。

  • ~.bash_profile ログイン時に一度だけ実行される
  • ~.bashrc bashが読み込まれる度に更新される

bashが読み込まれるタイミング」というのは、

  1. ~.bash_profile が読み込まれるとき = ログイン時(.bashrc.bash_profileから呼び出しているから)
  2. bashコマンドを叩いた時

環境変数の設定はログイン時に行えればいいので、~.bash_profileに設定が望ましい。

# .bash_profileに設定
[vagrant@localhost ~]$ vi ~./bash_profile
# (略)

.bash_profileの変更の反映には、1.ログインしなおすか、2.sourceコマンドを実行する。

1. ログインしなおして反映する場合
# 書き込みを反映させるためにログアウトする(rootユーザーへ)
[vagrant@localhost ~]$ su -
パスワード: # パスワード入力

# 元のユーザーに戻る(「-」を忘れない)
[root@localhost ~]# su - vagrant
[vagrant@localhost ~]
2. sourceコマンドで反映する場合
[vagrant@localhost ~]$ source ~/.bash_profile

※自分の環境ではsourceコマンドでの場合、~/.bash_profile追記したときは問題ないが、削除した場合は反映がされなかった。(helloコマンドが実行できてしまう)

.bashrc.bash_profileについての話は下記記事が参考になった。

管理者ユーザーになる

管理者ユーザーでしか操作できない(読み・書き・実行が行えない)ファイルを操作するためには、ユーザーを変更して管理者ユーザーになる必要がある。

例えば、システムのログファイル(/var/log/messages)を確認したいとする。

# ファイルの詳細を確認
[vagrant@localhost ~]$ ls -l /var/log/messages
-rw-------. 1 root root 55861  1月 20 19:58 2018 /var/log/messages

管理者(root)ユーザーにしか読み書きの権限がないため管理者ユーザーに切り替える。
任意のユーザーに切り替えるためにはsuコマンド(substitute user)を使う。

  • ユーザー名を省略するとrootユーザーになる
  • -lオプションをつけるとrootユーザーとしてログインし直す。
    -lをつけないと、ユーザーを切り替えるのみで、現在のディレクトリの位置や環境変数をそのまま引き継ぐ
    • 通常はログインし直した方が良いためsu -lで良いが、lは省略できるためsu -というコマンドが良く使われる
[vagrant@localhost ~]$ su -
パスワード: # ローカル開発環境では「vagrant」がパスワード 
# ログイン完了
[root@localhost ~]# 

この状態であれば/var/log/messagesファイルを確認できる。

[root@localhost ~]# cat /var/log/messages

管理者ユーザーとして実行する

上記の、管理者ユーザーへ変更してからの操作は、権限が広すぎるためミスすると大変なことになりかねない。

そのため一般的には管理者ユーザーに切り替えるのではなく、sudoを使ってコマンド単位で管理者ユーザーとして実行する。

# vagrant ユーザーのまま実行できる
[vagrant@localhost ~]$ sudo cat /var/log/message

ファイルの所有者を変更する

chownchange owner)コマンドを使うとファイルの所有者を変更できる。

先ほどのログファイルを手元にコピーして編集する場合を想定。

まず、そのままコピーをしようとすると管理者ユーザーではないためエラーとなる。

[vagrant@localhost ~]$ cp /var/log/messages .
cp: `/var/log/messages' を 読み込み用でオープンできません: 許可がありません

sudoで実行するとうまくいく。

[vagrant@localhost ~]$ sudo cp /var/log/messages .

しかしこれを編集するとなるとまたsudoで実行しなくてはならず面倒なので、chownコマンドでこのファイルの所有者をrootから変更する。
chownコマンドもsudoから実行する必要があるので注意)

# 所有者がrootユーザーとrootグループであると確認
[vagrant@localhost ~]$ ls -l messages
-rw-------. 1 root root 55861  1月 20 22:49 2018 messages

# ユーザーとグループをそれぞれvagrantに変更
[vagrant@localhost ~]$ sudo chown vagrant:vagrant messages

# 正しく変更されているのを確認
[vagrant@localhost ~]$ ls -l messages 
-rw-------. 1 vagrant vagrant 55861  1月 20 22:49 2018 messages

これで読み書き権限が付いたので編集が可能となった。

テキストを操作する

コマンド 説明
wc (word count)
行数、単語数、バイト数、ファイル名の順に表示
日本語は英語と異なり、単語の区切りが空白やタブではないため正確な単語数は出てこない
-l --lines 行数を表示
-w --words 単語数を表示
-m -chars 文字数を表示
-c -bytes バイト数を表示
head ファイルの先頭を表示(デフォルトでは先頭10行)
-〇 n - 〇 先頭から〇行表示(0だと表示なし)
-v ファイルごとにファイル名を出力
head -vn 3 a.txt b.txt(先頭3行表示されるため簡単な比較をしたいときに便利かも)
tail ファイルの末尾を表示(デフォルトでは末尾10行)
他はほぼheadと同じ
grep ファイルの中から文字列を検索
※オプションが豊富で正規表現での検索も可能。詳しくはまた別途。

ファイルディスクリプタ、リダイレクション、パイプ

ファイルディスクリプタとは

UNIXでは標準入力、標準出力、標準エラー出力という3つのファイルディスクリプタと呼ばれるものが存在する。

ファイルディスクリプタとは、はっきりとはよくわからないが、下記の記事が分かりやすかった。

ここに書かれているように「ファイルを識別するための目印」というイメージでいる。

リダイレクションとは

基本的に、

  • 標準入力はキーボード
  • 標準出力はディスプレイ
  • 標準エラー出力はディスプレイ

という具合でデバイス(装置)とディスクリプタは紐づいているが、この入出力先を変更することをリダイレクションという。
この説明だと抽象的で微妙なので具体的な例で言うと、処理結果をファイルに出力したり、逆に処理内容をファイルから呼び出したりすることである。

リダイレクションを行うためのコマンドは下記になる。

コマンド 説明
a > b aの処理結果をbに出力(bがすでにあれば上書き)
a >> b aの処理結果をbの末尾に追記
a < b aの処理内容をbから入力

サンプル

# 'hello'文字列をhello.txtに保存
$ echo 'hello' > hello.txt
# hello.txtの末尾に'world'を追加
$ echo 'world' >> hello.txt
# 結果確認
$ cat hello.txt 
hello
world
# 「echo 'hello'」と内容が書かれたhello.txtがあるとする
$ bash < hello.txt
hello

組み合わせての実行もできる。

# 「echo 'hello'」と内容が書かれたhello.txtがあるとする
$ bash < hello.txt > result.txt
# 結果確認
$ cat result.txt
hello

パイプとは

コマンドの処理結果(出力)を別のコマンドに振り分けることをパイプという。

パイプを行うためのコマンドは下記になる。

コマンド 説明
`a b| aの処理結果をbに渡す<br>※パイプは複数つなげることできる<br>a | b | c | d |...`

サンプル

# 'hello'文字列の文字数表示
$ echo 'hello' | wc -m
6

上記は非常に簡単な例だが、wc -mに渡される内容が'hello'となっていることが分かる。
もう少し実用的なサンプルで確かめてみる。

# /etc直下のディレクトリから'conf'が含まれているリストを作ってその行数を出力
$ ls -l /etc | grep 'conf' | wc -l
34

使いこなせば複雑な処理も1行で記述できるようになりそうである。

ワイルドカード

そもそもワイルドカードとは

もともとカードゲームのワイルドカードに由来するもので、他のカードの代用が可能な特殊なカードのことをいうようである。
コンピューターに関しても同じことがいえて、検索などのgrobの際に使用する特殊文字の種類で、どんな文字列にもマッチするもののことをワイルドカードという。

このような特性を持つワイルドカードを活用するとより便利にコマンド操作が行える。
UNIXコマンドでは下記のワイルドカードが使える。

コマンド 説明
* 0文字以上の任意の文字列
? 1文字のみの任意の文字列

サンプル

# logフォルダの中から拡張子が.logのものを表示
$ ls /var/log/*.log
/var/log/VBoxGuestAdditions.log  /var/log/anaconda.log          /var/log/anaconda.storage.log  /var/log/boot.log    /var/log/mysqld.log               /var/log/vboxadd-install.log
/var/log/anaconda.ifcfg.log      /var/log/anaconda.program.log  /var/log/anaconda.yum.log      /var/log/dracut.log  /var/log/vboxadd-install-x11.log  /var/log/yum.log
# logフォルダの中から.(ドット)の前から3文字前が「y」の.logファイルを表示
$ ls /var/log/*y??.log
/var/log/anaconda.yum.log  /var/log/yum.log

ファイル、ディレクトリの検索

先に紹介したgrepコマンドはファイルの中身に関して検索をしたが、ファイルやディレクトリの検索にはfindコマンドを使う。

findコマンドの基本的な使い方は下記。

$ find {検索開始ディレクトリ} {検索条件} 

findは「検索開始ディレクトリ」に指定されたディレクトリに対して再帰的に検索をかける。
そのため$ find ~ ...とするとホームディレクトリ配下全ファイル対象に検索する。

検索条件ではいろいろと複雑な条件指定が可能。
ひとまずシンプルな検索条件を見てみる。
例)
-type d ディレクトリのみを検索
-type f ファイルのみを検索
-name {filename} ファイル名で検索

# /var/log/ディレクトリ配下にある.logファイルを出力
# (読み取り権限に引っかかるものがあるので sudo コマンドで実行)
$ sudo find /var/log/ -name "*.log"
/var/log/yum.log
/var/log/anaconda.yum.log
/var/log/anaconda.program.log
/var/log/boot.log
...

検索したファイルに対して別のコマンドを実行

大きく2つの方法がある。

1. -execオプションを使う方法

書き方がぱっと見は少し独特。

# /var/log/ディレクトリ配下にある.logファイルの文字数をそれぞれ表示
$ sudo find /var/log/ -name "*.log" -exec wc -m {} +
  20820 /var/log/yum.log
  32257 /var/log/anaconda.yum.log
  29439 /var/log/anaconda.program.log
    2613 /var/log/boot.log
  ...

要は-execコマンドでつないだ後、{}に、findで出力されたものが入るということ。そう理解できると難しくはない。

末尾の +\; の違い

下記のコマンドは似ているが実はロジックが少し異なっている。

$ sudo find /var/log/ -name "*.log" -exec wc -m {} +
  20820 /var/log/yum.log
  32257 /var/log/anaconda.yum.log
  29439 /var/log/anaconda.program.log
   2613 /var/log/boot.log
...

$ sudo find /var/log/ -name "*.log" -exec wc -m {} \;
20820 /var/log/yum.log
32257 /var/log/anaconda.yum.log
29439 /var/log/anaconda.program.log
2613 /var/log/boot.log
...

処理結果を見ると分かるのだが、 + を使った場合、 {} に入っているリストに対して、まとめて wc -m コマンドを実行している。つまり下記と同じ意味。

$ sudo wc -m /var/log/yum.log /var/log/anaconda.yum.log /var/log/anaconda.program.log /var/log/boot.log ...

対して \; を使った場合は、{} に入っているリストに対して、1つずつコマンドを実行している。つまり下記と同じ意味。

$ sudo wc -m /var/log/yum.log
$ sudo wc -m /var/log/anaconda.yum.log
$ sudo wc -m /var/log/anaconda.program.log
$ sudo wc -m /var/log/boot.log
...

どちらもほぼ同じ結果だが、+ を使った場合の方が処理コスト的には低くて高速に動作しそうではある。

このあたりの参考としては下記記事が分かりやすかった。

2. xargsコマンドを使う方法

下記のコマンドは同一の内容である。

# -execを使う
$ sudo find /var/log/ -name "*.log" -exec wc -l {} +

# xargsを使う(自分の場合、xargsの前にsudoが必要であった)
$ sudo find /var/log/ -name "*.log" | sudo xargs wc -l

xargsは、複数の結果をコマンドへ送りだすことができるコマンド。
-execとは異なり、findの結果に限らない。
例えば下記のようにlsを使って「ディレクトリ直下にある.txtファイルそれぞれの先頭一行だけを表示する」ということも可能。

$ ls *.txt | xargs head -1

ブレース展開

ブレースとは{}のことで、{}の中にカンマ区切りやドットを2つ続けて文字列や数値を記述すると、コマンド実行時に展開される。

$ echo {1,2,3}
1 2 3

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

{}の前に文字列や数値、{}を続けて書くと、数学の展開のように展開が可能。

# a(1+2+3) のような展開
$ echo a{1..3}
a1 a2 a3

# (a+b+c)(1+2)(x+y+z) のような展開
$ echo {a,b,c}{1,2}{x,y,z}
a1x a1y a1z a2x a2y a2z b1x b1y b1z b2x b2y b2z c1x c1y c1z c2x c2y c2z

この特性を生かすと様々な操作が効率的に行える。

# ディレクトリを一気に作成
$ mkdir test{1..5}

# 作成したディレクトリにファイルを挿入
$ touch !$/file{1..3}{.txt,.png}

# 確認
$ ls test{1..5}
test1:
file1.png  file1.txt  file2.png  file2.txt  file3.png  file3.txt

test2:
file1.png  file1.txt  file2.png  file2.txt  file3.png  file3.txt
...

# すべてのファイルから.pngだけ削除する
$ rm test{1..5}/*.png

# 確認
$ ls test{1..5}
test1:
file1.txt  file2.txt  file3.txt

test2:
file1.txt  file2.txt  file3.txt
...

他にも多数あり、下記が詳しくまとまっている。