以下はAndrewによる記事、101 Bash Commands and Tips for Beginners to Expertsの日本語訳です。
一部を除き、上から順にコマンドを打って確かめることができるようになっています。
読むだけではなく、実際に打って試してみることで理解が早まることでしょう。
101 Bash Commands and Tips for Beginners to Experts
一年前まで、私はもっぱらMacOSとUbuntuのふたつのOSで作業をしていました。
両OSにおいて、私のデフォルトシェルはbashです。
過去6、7年ほどbashで仕事をしているため、bashがどのように動作するか、ある程度は理解しているつもりです。
従って、bashを始めたばかりの人にとって一般的で有用なコマンドについて、いくつか解説していきたいと思います。
また、bashについて知っているべきことを全て知っていると思っている人も、とりあえず見ていってください。
あなたが忘れているかもしれない、使うことで仕事がより簡単になるかもしれない、TIPSやリマインダのヒントを鏤めました。
以下のコマンドは段階を踏んで進んでいくので、bashを使い始めたばかりであっても、最初から最後まで順番に進んでいくことができます。
最初は簡単で、徐々に難しく一般的ではないコマンドを出していきます。
The Basics
First Commands, Navigating the Filesystem
最初のコマンドはファイルシステムのナビゲーション。
最近のファイルシステムはディレクトリツリー構造を持っています。
ディレクトリは親のないルートディレクトリ、もしくは一つの親を持つサブディレクトリのいずれかです。
ディレクトリツリーを逆方向(子から親へ)移動し続けると、最終的には必ずルートディレクトリに到達します。
一部のファイルシステムには複数のルートディレクトリを持つものもありますが(WindowsのC:\、A:\など)、UnixやUnixライクOSには単一のルートディレクトリ/しかありません。
pwd / ls / cd
ファイルシステム内で作業する場合、ユーザは常にどこかのディレクトリ、すなわちカレントディレクトリもしくは作業ディレクトリと呼ばれる場所にいます。
カレントディレクトリはpwdコマンドで確認することができます。
[ andrew@pc01 ~ ]$ pwd
/home/andrew
カレントディレクトリの中身、ファイルや子ディレクトリなどを参照するのはlsコマンドです。
[ andrew@pc01 ~ ]$ ls
Git TEST jdoc test test.file
おまけ
ls -aで隠しファイル(.で始まるなど)を表示する。
ls -lでファイルの詳細も表示する。
ls -l -aのように複数のオプションを連ねられる。
ls -l -aのかわりにls -laと書くこともできる。
カレントディレクトリを変更するのはcdコマンドです。
[ andrew@pc01 ~ ]$ cd TEST/
[ andrew@pc01 TEST ]$ pwd
/home/andrew/TEST
[ andrew@pc01 TEST ]$ cd A
[ andrew@pc01 A ]$ pwd
/home/andrew/TEST/A
cd ..で親ディレクトリに移動することができます。
[ andrew@pc01 A ]$ cd ..
[ andrew@pc01 TEST ]$ pwd
/home/andrew/TEST
cd ~あるいは単にcdで、どこからでもユーザのホームディレクトリ(通常は/home/username)に戻ってきます。
[ andrew@pc01 TEST ]$ cd
[ andrew@pc01 ~ ]$ pwd
/home/andrew
おまけ
cd ~userは、"userのホームディレクトリにcd"という意味。
cd ../..のように一気に多段ディレクトリ移動ができる。
ひとつ前にいたディレクトリに戻るのはcd -。
.はカレントディレクトリのこと。よってcd .は何もしない。
; / && / &
コマンドラインに入力するのはコマンドと呼ばれるもので、そしてコマンドはPCのどこかに保存されているプログラムを実行させます。
このプログラムはLinuxのビルトインコマンドであることもあれば、誰かが作ったアプリであることもあり、そしてあなたが作ったコードであるかもしれません。
時折、複数のコマンドを連続して実行したいことがあります。
そのためにはセミコロン;を使います。
[ andrew@pc01 ~ ]$ ls; pwd
Git TEST jdoc test test.file
/home/andrew
上のコマンドは、まずlsでカレントディレクトリの中身を表示し、次いでpwdでカレントディレクトリの位置を表示します。
コマンドを連続実行するためのもうひとつ便利なツールが&&です。
これを使うと、左側のコマンドが失敗した場合は右のコマンドが実行されません。
;や&&は連続で使うことができます。
# cdでtypoしたのでpwd以降は実行されない
[ andrew@pc01 ~ ]$ cd /Giit/Parser && pwd && ls && cd
-bash: cd: /Giit/Parser: No such file or directory
# 成功したので後続のコマンドも実行される
[ andrew@pc01 ~ ]$ cd Git/Parser/ && pwd && ls && cd
/home/andrew/Git/Parser
README.md doc.sh pom.xml resource run.sh shell.sh source src target
;を使った場合は、手前のコマンドが失敗したとしても後ろのコマンドが実行されます。
# pwdに失敗したけどpwdやlsが動く
[ andrew@pc01 ~ ]$ cd /Giit/Parser ; pwd ; ls
-bash: cd: /Giit/Parser: No such file or directory
/home/andrew
Git TEST jdoc test test.file
&は一見&&と似たように見えますが、実際は全く異なる機能です。
実行に長い時間がかかるコマンドを実行すると、そのコマンドの実行が終了するまでコマンドラインは何もできなくなります。
コマンドの後ろに&を書くと待ちが発生しなくなり、古いコマンドがまだ動いている状態でも、次のコマンドを実行することができるようになります。
[ andrew@pc01 ~ ]$ cd Git/Parser && mvn package & cd
[1] 9263
おまけ
&を使ってコマンドを隠すことを、我々はジョブ(あるいはプロセス)のバックグラウンド化と呼んでいる。
現在バックグラウンド状態のジョブはjobsコマンドで確認することができる。
[ andrew@pc01 ~ ]$ jobs
[1]+ Running cd Git/Parser/ && mvn package &
Getting Help
-h
ほとんどのコマンドは、-hあるいは--helpでコマンドのヘルプを表示してくれます。
[ andrew@pc01 ~ ]$ du --help
Usage: du [OPTION]... [FILE]...
or: du [OPTION]... --files0-from=F
Summarize disk usage of the set of FILEs, recursively for directories.
Mandatory arguments to long options are mandatory for short options too.
-0, --null end each output line with NUL, not newline
-a, --all write counts for all files, not just directories
--apparent-size print apparent sizes, rather than disk usage; although
the apparent size is usually smaller, it may be
larger due to holes in ('sparse') files, internal
fragmentation, indirect blocks, and the like
-B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,
'-BM' prints sizes in units of 1,048,576 bytes;
see SIZE format below
...
man
大抵のコマンドは、manコマンドに続けて打つとコマンドのマニュアルを表示することができます。
qでマニュアルを終了します。
LS(1) User Commands LS(1)
NAME
ls - list directory contents
SYNOPSIS
ls [OPTION]... [FILE]...
DESCRIPTION
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is speci-
fied.
Mandatory arguments to long options are mandatory for short options
too.
...
Viewing and Editing Files
head / tail / cat / less
headはファイルの最初の数行を出力します。
出力行数のデフォルトは10で、-nで変更できます。
# 最初の3行を表示
[ andrew@pc01 ~ ]$ head -n 3 c
this
file
has
tailは逆にファイルの最後の数行を出力します。
出力行数はheadと同じように指定するか、もしくは-n +NでN行目から最後までを出力できます。
# 4行目から最後までを表示
[ andrew@pc01 ~ ]$ tail -n +4 c
exactly
six
lines
catは複数のファイルを連結し、その結果を標準出力(通常はターミナル)に送信します。
しかしこのコマンドは、複数のファイルや、単に1ファイルの中身をさっと確認するために使われることがしばしばあります。
そのような使い方をすると猫の無駄遣いで告発される可能性がありますが、たいした害はないので気にしなくてもかまいません。
[ andrew@pc01 ~ ]$ cat a
file a
[ andrew@pc01 ~ ]$ cat a b
file a
file b
ファイルを素早く表示するもうひとつの方法がlessで、これを使うと読み取り専用のvimのようなウィンドウが開きます。
実はmoreというコマンドもあるのですが、lessのほうが優位なので出番はありません。
もっと詳しく(more)、いや少なく?(less)知りたい場合は、lessとmoreのmanページを参照してください。
nano / nedit
nanoは必要最小限のコマンドラインテキストエディタです。
初心者や、100万のショートカットを覚えたくないユーザにとっては最適の優れたエディタです。
私のキャリアにおいても、最初の数年間はnanoだけで十分でした。
nanoで独自のシンタックスハイライトを定義するのは大変なので、さすがにそろそろ別の強力なエディタを検討し始めていますが。
neditは小規模なグラフィカルテキストエディタで、X Windowを開き、クリック編集、ドラッグアンドドロップ、構文強調表示等が可能です。
スクリプトに小さな変更を加えながら何度も実行したいとき、私はよくneditを使用します。
その他の一般的なCLI/GUIテキストエディタとして、emacs、vi、vim、gedit、Notepad++、Atom、そしてその他たくさんの選択肢が存在します。
私が触った中でも特に魅力的で推奨できると感じたものは、Micro、Light Table、そしてVS Codeです。
最近のエディタは全て、検索、置換、構文強調表示などの便利機能を標準装備しています。
viやemacsはnanoやneditより遙かに多くの機能がありますが、同時に学習曲線も急坂です。
エディタを色々試してみて、自分に合ったものを探してみてください。
Creating and Deleting Files and Directories
ファイル・ディレクトリの作成と削除。
touch
touchはファイルのタイムスタンプを更新するために作られたものですが、空のファイルを作るためにも利用できます。
nanoなどのテキストエディタで新規ファイルを作成してみましょう。
[ andrew@pc01 ex ]$ ls
[ andrew@pc01 ex ]$ nano a
/* ここで保存してエディタを終了 */
[ andrew@pc01 ex ]$ ls
a
touchなら1コマンドです。
[ andrew@pc01 ex ]$ touch b && ls
a b
おまけ
Ctrl+zで現在実行中のプロセスをバックグラウンドにできる。
fgコマンドでプロセスに戻る。
[ andrew@pc01 ex ]$ nano a
/* ここでCtrl + z */
Use fg to return to nano
[1]+ Stopped nano a
[ andrew@pc01 ex ]$ fg
/* 編集画面に戻った */
さらにおまけ
Ctrl+cだと現在実行中のプロセスを強制終了する。
バックグラウンドプロセスを強制終了するにはkill %N。
Nに入れるプロセス番号はjobsコマンドで確認できる。
mkdir / rm / rmdir
空のディレクトリを作るのはmkdirコマンドです。
[ andrew@pc01 ex ]$ ls && mkdir c && ls
a b
a b c
rmでファイルを削除できますが、削除すると元に戻せません。
注意してください。
[ andrew@pc01 ex ]$ rm a && ls
b c
削除確認の警告を行いたい場合は-iオプションを追加しましょう。
[ andrew@pc01 ex ]$ rm -i b
rm: remove regular empty file 'b'? y
空のディレクトリを削除するのはrmdirです。
空のディレクトリでls -aすると、カレントディレクトリ.と親ディレクトリ..だけが表示されます。
[ andrew@pc01 ex ]$ rmdir c && ls -a
. ..
rmdirでは、空でないディレクトリは削除できません。
[ andrew@pc01 ex ]$ cd .. && ls test/
*.txt 0.txt 1.txt a a.txt b c
[ andrew@pc01 ~ ]$ rmdir test/
rmdir: failed to remove 'test/': Directory not empty
中身の入ったディレクトリを全て強制的に削除するには、rm -rfを使います。
-rは再帰、-fは強制実行するオプションです。
[ andrew@pc01 ~ ]$ rm –rf test
Moving and Copying Files, Making Links, Command History
ファイルの移動、コピー、リンク、コマンド履歴。
mv / cp / ln
ファイルの移動、リネームはmvです。
ディレクトリを移動してファイル名をそのままにする、ファイル名もついでに変更するといったことができます。
[ andrew@pc01 ex ]$ ls && mv a e && ls
a b c d
b c d e
コピーはcpです。
[ andrew@pc01 ex ]$ cp e e2 && ls
b c d e e2
lnはファイルへのハードリンクを作成します。
# 第一引数が対象ファイル、第二引数がリンク名
[ andrew@pc01 ex ]$ ln b f && ls
b c d e e2 f
ln -sでシンボリックリンクが作成できます。
[ andrew@pc01 ex ]$ ln -s b g && ls
b c d e e2 f g
ハードリンクは同じメモリを参照するひとつのファイルへの別名を作ります。
シンボリックリンクは元のファイル名を追跡するだけで、ファイル実体を参照するのは元ファイルだけです。
これ以上の詳細についてはWhat is the difference between a symbolic link and a hard link?を見てください。
Command History
bashは、実行したコマンドを再実行するために役立つ機能をふたつ持っています。
ひとつめの機能はタブ補完です。
コマンドの一部を入力したところでTABを押すと、何を打とうとしているのか端末が推測してくれます。
[ andrew@pc01 dir ]$ ls <ENTER>
anotherlongfilename thisisalongfilename anewfilename
[ andrew@pc01 dir ]$ ls t <TAB>
TABを押すと、以下のようにコマンドが最後まで補完されます。
[ andrew@pc01 dir ]$ ls thisisalongfilename <ENTER>
thisisalongfilename
特定しきれない場合はTABを何度か押すことになります。
[ andrew@pc01 dir ]$ ls a <TAB>
[ andrew@pc01 dir ]$ ls an <TAB>
anewfilename anotherlongfilename
bashは以前に実行したコマンドを幾つか覚えており、Ctrl+Rでその履歴を検索することができます。
(reverse-i-search)`':
ここでanewと入力すると、その文字が含まれるコマンドのうち最後に実行したものが出てきます。
(reverse-i-search)`anew': touch anewfilename
Directory Trees, Disk Usage, and Processes
ディレクトリツリー、ディスク使用量、プロセス。
mkdir –p / tree
mkdirはデフォルトではひとつのディレクトリのみを作成します。
どういうことかというと、ディレクトリd/eが存在しないときにディレクトリd/e/fを作ることはできないということです。
[ andrew@pc01 ex ]$ ls && mkdir d/e/f
a b c
mkdir: cannot create directory 'd/e/f': No such file or directory
-pオプションを付けることで、深い階層のディレクトリも一気に作成してくれます。
[ andrew@pc01 ex ]$ mkdir -p d/e/f && ls
a b c d
treeコマンドはディレクトリツリーをいいかんじにビジュアル化して表示してくるので、ディレクトリ構造を把握するのに役立ちます。
デフォルトでは指定ディレクトリ以下のディレクトリツリーを全て示しますが、-Lオプションで階層を限定することもできます。
[ andrew@pc01 ex ]$ tree -L 2
.
|-- a
|-- b
|-- c
`-- d
`--e
3 directories, 2 files
空のディレクトリを表示させたくないときは--pruneオプションを使います。
このオプションは再帰的なので、空のディレクトリだけが入った空でないディレクトリも消えることに注意しましょう。
[ andrew@pc01 ex ]$ tree --prune
.
|-- a
`-- b
df / du / ps
dfはディスクおよびシステムの容量がどれだけ使用されているかを一覧表示します。
[ andrew@pc01 ex ]$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 126G 0 126G 0% /dev
tmpfs 26G 2.0G 24G 8% /run
/dev/mapper/ubuntu--vg-root 1.6T 1.3T 252G 84% /
...
このコマンドにおいては、-hオプションは"ヘルプ表示"ではなく"人間が見てわかりやすく表示"を意味します。
いくつかのコマンドは、このオプションを使うことで、バイト数そのままではなくキロバイトK、ギガバイトGなどでファイルやディスク容量を出力してくれます。
duは指定ディレクトリとそのサブディレクトリの使用量を表示します。
あるハードディスクの使用量を知りたい場合はdf、あるディレクトリの使用量を知りたいときはduを使います。
[ andrew@pc01 ex ]$ du
4 ./d/e/f
8 ./d/e
12 ./d
4 ./c
20 .
duは--max-depth=Nオプションを受け取り、指定した階層のディレクトリまでを表示します。
[ andrew@pc01 ex ]$ du -h --max-depth=1
12K ./d
4.0K ./c
20K .
psはユーザが実行中の全てのプロセス(ジョブ)を表示します。
[ andrew@pc01 ex ]$ ps
PID TTY TIME CMD
16642 pts/15 00:00:00 ps
25409 pts/15 00:00:00 bash
Miscellaneous
passwd / logout / exit
パスワード変更コマンドはpasswdです。
確認のために現在のコマンドを一回と、変更後のパスワードを2回入力する必要があるため、入力ミスすることはないでしょう。
[ andrew@pc01 dir ]$ passwd
Changing password for andrew.
(current) UNIX password: <現在のパスワード>
Enter new UNIX password: <新パスワード>
Retype new UNIX password: <新パスワードを再入力>
passwd: password updated successfully
logoutで現在のログインシェルが終了します。
[ andrew@pc01 dir ]$ logout
──────────────────────────────────────────────────────────────────────────────
Session stopped
- Press <return> to exit tab
- Press R to restart session
- Press S to save terminal output to file
exitはサブシェルを含め全て終了します。
[ andrew@pc01 ~ ]$ exit
logout
──────────────────────────────────────────────────────────────────────────────
Session stopped
- Press <return> to exit tab
- Press R to restart session
- Press S to save terminal output to file
clear / *
clearを実行するとカーソルが画面の一番上に移動します。
実際やってることは現在の行の下に空白行を追加しているだけですが、ワークスペースをクリアするのに有用です。
ファイルの検索にはglob(*、ワイルドカード、Kleene Star)が便利です。
以下の2コマンドの違いについて注意してください。
[ andrew@pc01 ~ ]$ ls Git/Parser/source/
PArrayUtils.java PFile.java PSQLFile.java PWatchman.java
PDateTimeUtils.java PFixedWidthFile.java PStringUtils.java PXSVFile.java
PDelimitedFile.java PNode.java PTextFile.java Parser.java
[ andrew@pc01 ~ ]$ ls Git/Parser/source/PD*
Git/Parser/source/PDateTimeUtils.java Git/Parser/source/PDelimitedFile.java
globは1コマンド中に何度も使用することができ、"0文字以上の文字列"に一致します。
[ andrew@pc01 ~ ]$ ls Git/Parser/source/P*D*m*
Git/Parser/source/PDateTimeUtils.java Git/Parser/source/PDelimitedFile.java
Intermediate
Disk, Memory, and Processor Usage
ncdu
ncdu(NCurses Disk Usage)はファイル使用量の概要を表示する、改善版duのようなコマンドです。
読み取り専用のvimのようなウィンドウが開くので、終了する際はqを押しましょう。
[ andrew@pc01 ~ ]$ ncdu
ncdu 1.11 ~ Use the arrow keys to navigate, press ? for help
--- /home/andrew -------------------------------------------------------------
148.2 MiB [##########] /.m2
91.5 MiB [###### ] /.sbt
79.8 MiB [##### ] /.cache
64.9 MiB [#### ] /.ivy2
40.6 MiB [## ] /.sdkman
30.2 MiB [## ] /.local
27.4 MiB [# ] /.mozilla
24.4 MiB [# ] /.nanobackups
10.2 MiB [ ] .confout3.txt
8.4 MiB [ ] /.config
5.9 MiB [ ] /.nbi
5.8 MiB [ ] /.oh-my-zsh
4.3 MiB [ ] /Git
3.7 MiB [ ] /.myshell
1.7 MiB [ ] /jdoc
1.5 MiB [ ] .confout2.txt
1.5 MiB [ ] /.netbeans
1.1 MiB [ ] /.jenv
564.0 KiB [ ] /.rstudio-desktop
Total disk usage: 552.7 MiB Apparent size: 523.6 MiB Items: 14618
top / htop
topは、現在実行されている全てのプロセスと所有者、メモリ使用量などを表示します。
そしてhtopはインタラクティブな改良版topです。
いずれも-u usernameオプションで該当ユーザのプロセスだけを表示することができます。
REPLs and Software Versions
REPLs
REPLはRead-Eval-Print Loopの略で、コマンドラインと同じようなものですが、通常はプログラミング言語との対話的ウィンドウに対して呼ばれます。
PythonのREPLはpythonコマンドで始めることができ、quit()関数で終了します。
[ andrew@pc01 ~ ]$ python
Python 3.5.2 (default, Nov 12 2018, 13:43:14) ...
>>> quit()
RのREPLはRコマンドで始まり、q()関数で終了です。
[ andrew@pc01 ~ ]$ R
R version 3.5.2 (2018-12-20) --"Eggshell Igloo" ...
> q()
Save workspace image? [y/n/c]: n
ScalaのREPLはscalaコマンドで始まり、quitコマンドで終了です。
[ andrew@pc01 ~ ]$ scala
Welcome to Scala 2.11.12 ...
scala> :quit
JavaのREPLはjshellコマンドで始まり、/exitコマンドで終了です。
[ andrew@pc01 ~ ]$ jshell
| Welcome to JShell--Version 11.0.1 ...
jshell> /exit
これらのREPLはCtrl+dでも終了できます。
Ctrl+dはUnixのEOFであり、入力の終端を意味します。
-version / --version / -v
ほとんどのコマンドやプログラムは、そのソフトウェアバージョンを表示する-versionもしくは--versionオプションがあります。
ほとんどのアプリケーションにも同じオプションが用意されています。
[ andrew@pc01 ~ ]$ ls --version
ls (GNU coreutils) 8.25 ...
[ andrew@pc01 ~ ]$ ncdu -version
ncdu 1.11
[ andrew@pc01 ~ ]$ python --version
Python 3.5.2
ただし、稀にあまり馴染みのないオプションも存在します。
[ andrew@pc01 ~ ]$ sbt scalaVersion
...
[info] 2.12.4
バージョンを表すオプションとして-vを使うプログラムもあります。
しかし多くの場合-vは'verbose'を意味し、診断情報やデバッグ情報といった多くの詳細情報も出力します。
SCP(1) BSD General Commands Manual SCP(1)
NAME
scp -- secure copy (remote file copy program)
...
-v Verbose mode. Causes scp and ssh(1) to print debugging messages
about their progress. This is helpful in debugging connection,
authentication, and configuration problems.
...
Environment Variables and Aliases
Environment Variables
環境変数("env vars"と略されることもある)は、bashシェル上で作成・使用できる永続変数のことです。
これらは=で定義し、$で参照します。
pritenvで現在定義されている全ての環境変数を確認することができます。
[ andrew@pc01 ~ ]$ printenv
SPARK_HOME=/usr/local/spark
TERM=xterm
...
新しい環境変数を定義しましょう。
=の前後にスペースを入れてはいけません。
[ andrew@pc01 ~ ]$ myvar=hello
定義した環境変数はechoで取得できます。
ただし変数の頭に$を付けます。
[ andrew@pc01 ~ ]$ echo $myvar
hello
スペースやその他の空白を含む値を指定したいときは、値を"で囲まなければなりません。
また環境変数は警告無しに上書きできるので気をつけましょう。
[ andrew@pc01 ~ ]$ myvar="hello, world!" && echo $myvar
hello, world!
環境変数をexportコマンド付きで定義することもできます。
そうすると、サブシェル内でもその環境変数を参照することができるようになります。
[ andrew@pc01 ~ ]$ export myvar="another one" && echo $myvar
another one
環境変数の設定を解除するには、=の右側を空欄にして決定するか、unsetコマンドを使用します。
[ andrew@pc01 ~ ]$ unset mynewvar
[ andrew@pc01 ~ ]$ echo $mynewvar
Aliases
エイリアスは環境変数に似ていますが、普通は異なる目的で利用されます。
長いコマンドを短く置き換えるために使用されます。
[ andrew@pc01 apidocs ]$ ls -l -a -h -t
total 220K
drwxr-xr-x 5 andrew andrew 4.0K Dec 21 12:37 .
-rw-r--r-- 1 andrew andrew 9.9K Dec 21 12:37 help-doc.html
-rw-r--r-- 1 andrew andrew 4.5K Dec 21 12:37 script.js
...
[ andrew@pc01 apidocs ]$ alias lc="ls -l -a -h -t"
[ andrew@pc01 apidocs ]$ lc
total 220K
drwxr-xr-x 5 andrew andrew 4.0K Dec 21 12:37 .
-rw-r--r-- 1 andrew andrew 9.9K Dec 21 12:37 help-doc.html
-rw-r--r-- 1 andrew andrew 4.5K Dec 21 12:37 script.js
...
エイリアスの削除はunaliasです。
[ andrew@pc01 apidocs ]$ unalias lc
[ andrew@pc01 apidocs ]$ lc
The program 'lc' is currently not installed. ...
おまけ
環境変数とエイリアスの違い。
一部のプログラムでは、そのプログラム専用のエイリアスを設定できる。gitの例。
Basic bash Scripting
bash Scripts
bashスクリプト(シェルスクリプト)を使うと、複雑なプロセスを自動化し、再利用可能な形にパッケージ化することができます。
拡張子は通常.shです。
bashスクリプトには、通常のコマンドをいくらでも詰め込むことができます。
[ andrew@pc01 ~ ]$ echo "ls && touch file && ls" > ex.sh
作成したシェルスクリプトは、sourceもしくはshコマンドで実行可能です。
[ andrew@pc01 ~ ]$ source ex.sh
Desktop Git TEST c ex.sh project test
Desktop Git TEST c ex.sh file project test
chmodコマンドで、シェルスクリプトを直接実行可能にすることができます。
詳しくは後で解説します。
[ andrew@pc01 ~ ]$ echo "ls && touch file2 && ls" > ex2.sh
[ andrew@pc01 ~ ]$ chmod +x ex2.sh
実行権限+xのついたシェルスクリプトは、頭に./を付けることで直接実行できます。
[ andrew@pc01 ~ ]$ ./ex2.sh
Desktop Git TEST c ex.sh ex2.sh file project test
Desktop Git TEST c ex.sh ex2.sh file file2 project test
長いスクリプトを書きたい場合、行の最後に\を入れることで改行して入力できます。
[ andrew@pc01 ~ ]$ echo "for i in {1..3}; do echo \
> \"Welcome \$i times\"; done" > ex3.sh
シェルスクリプトにはもちろん、ループや関数などの複雑な構造も仕込むことができます。
[ andrew@pc01 ~ ]$ source ex3.sh
Welcome 1 times
Welcome 2 times
Welcome 3 times
Custom Prompt and ls
bashスクリプティングは、あなたの人生をずっと楽に、豊かに、カラフルにしてくれます。
この素晴らしいチートシートをご覧ください。
ところでシェルのプロンプトに出てくる文字列も環境変数で定義されていて、その名前は$PS1です。
他にもプロンプトはあって、それらについてはこちらを見てください。
[ andrew@pc01 ~ ]$ printf "%q" $PS1
$'\\n\\[\E[1m\\]\\[\E[30m\\]\\A'$'\\[\E[37m\\]|\\[\E[36m\\]\\u\\[\E[37m\\]@\\[\E[34m\\]\\h'$'\\[\E[32m\\]\\W\\[\E[37m\\]|'$'\\[\E(B\E[m\\]‘
デフォルトのプロンプトは、exportコマンドで変更可能です。
[ andrew@pc01 ~ ]$ export PS1="\ncommand here> "
command here> echo $PS1
\ncommand here>
色を付けることもできます。
command here> export PS1="\e[1;31m\nCODE: \e[39m"
# (ここ本当は赤いんだけどMarkdownで色の付け方がわからんかった)
CODE: echo $PS1
\e[1;31m\nCODE: \e[39m
lsが出力する色も環境変数$LS_COLORSで変更することができます。
CODE: ls
Desktop Git TEST c ex.sh ex2.sh ex3.sh file file2 project test
CODE: export LS_COLORS='di=31:fi=0:ln=96:or=31:mi=31:ex=92'
# (ここも本当は赤い)
CODE: ls
Desktop Git TEST c ex.sh ex2.sh ex3.sh file file2 project test
Config Files
Config Files / .bashrc
色々とコマンドを実行して設定を変更しましたが、いちどログアウトして再度ログインすると、全ての変更がリセットされてしまうことに気付くでしょう。
設定ファイルを使用することで、ログインしなおしてもシェルや特定のプログラムの設定を保持することができます。
bashシェルの主な設定ファイルは~/.bashrcです。
~/.bashrcに追加したエイリアス、環境変数、エイリアスは、ログインするたびに使用可能になります。
~/.bashrcに書かれたコマンドはログイン時に実行されるということです。
~/.bashrcを更新した場合、sourceコマンドでログアウトせずに最新状態にすることができます。
[ andrew@pc01 ~ ]$ nano ~/.bashrc
そして最初にecho "~/.bashrc loaded!"という行を付け加えてみましょう。
[ andrew@pc01 ~ ]$ source ~/.bashrc
~/.bashrc loaded!
ログアウトしてログインし直してもこうなります。
Last login: Fri Jan 11 10:29:07 2019 from 111.11.11.111
~/.bashrc loaded!
[ andrew@pc01 ~ ]
Types of Shells
ログインシェルとは、ログインしたとき最初に起動するシェルです。
対話型シェルとは、コマンドを入力することができるシェルです。
シェルには対話型ログインシェル、非ログイン非対話型シェル、あるいは他の組み合わせなど様々なものがあります。
~/.bashrc以外にも、ログインしたときやログアウトした際に自動的に実行されるスクリプトは幾つか存在します。
例を挙げると、
・/etc/profile
・~/.bash_profile
・~/.bash_login
・~/.profile
・~/.bash_logout
・/etc/bash.bash_logout
これらのスクリプトのどれが有効で、どの順番で実行されるかは、シェルのタイプによって異なります。
詳細についてはbashのmanページや、Stack Overflowのポストなどを参照してください。
bashはsourceコマンドで別のスクリプトを読み込むことも可能です。
たとえば~/.bashrcに以下を記載することができます。
source ~/.bashrc_addl
これにより、.bashrc_addlもsource対象のファイルとなります。
このファイルにも独自のエイリアス、関数、環境変数などを記述することができます。
同様に、さらに別のスクリプトをsourceすることもできます。
そうする場合はsourceが無限ループしないように注意してください。
機能やOS(Ubuntu、RedHat、macOS)などによってコマンドをファイルごとに分離しておくと役立つことがあります。
・~/.bash_ubuntu …Ubuntu固有の設定
・~/.bashrc_styles …PS1やLS_COLORSなど外観の設定
・~/.bash_java …言語ごとのの設定
外観やOS固有設定などをそれぞれ個別のファイルに切り出し、そしてそれらのうち必要なものをsourceするひとつの管理ファイルから構成します。
このような構成であれば、あらゆるマシンやOSで使用可能なシェルになります。
bash以外のシェルも存在することに気をつけてください。
bashは単にシェルの一種であるにすぎません。
他に一般的なシェルとしてはzsh、csh、fishなどが存在します。
様々なシェルを試して、自分に合ったものを見つけてください。
ただし、このチュートリアルはbashシェルで記述されているため、他のシェルでは動作しない可能性があることに注意してください。
Finding Things
whereis / which / whatis
whereisは、あるコマンドに対して、おそらく有用であろうファイルを検索します。
そのコマンドのバイナリすなわち実行可能なコード、ソースファイル、マニュアルのmanページなどです。
[ andrew@pc01 ~ ]$ whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1.gz
whichはバイナリ、すなわちコマンドの場所のみを返します。
[ andrew@pc01 ~ ]$ which ls
/bin/ls
whatisはmanページからコマンドの概要を1行表示します。
[ andrew@pc01 ~ ]$ whatis whereis which whatis
whereis (1) - locate the binary, source, and manual page files for a command
which (1) - locate a command
whatis (1) - display one-line manual page descriptions
whichは、エイリアスで隠蔽されているコマンドのオリジナルを探すのに役立ちます。
[ andrew@pc01 ~ ]$ alias ls="ls -l"
# エイリアスのせいで元コマンドと挙動が違う
[ andrew@pc01 ~ ]$ ls
total 36
drwxr-xr-x 2 andrew andrew 4096 Jan 9 14:47 Desktop
drwxr-xr-x 4 andrew andrew 4096 Dec 6 10:43 Git
...
# whichで調べた元コマンドを直接叩けばオリジナルの結果が得られる
[ andrew@pc01 ~ ]$ /bin/ls
Desktop Git TEST c ex.sh ex2.sh ex3.sh file file2 project test
locate / find
locateは、予め作成しておいたキャッシュリストを参照して高速にファイルを検索します。
[ andrew@pc01 ~ ]$ locate README.md
/home/andrew/.config/micro/plugins/gotham-colors/README.md
/home/andrew/.jenv/README.md
/home/andrew/.myshell/README.md
...
リストを検索するのでfindより高速ですが、必ずしも最新の状態と一致しているとは限りません。
findは実際のファイルシステムを検索して、探しているファイルを見つけます。
こちらは実ファイルを検索するため、常に最新のファイルを得ることができます。
[ andrew@pc01 ~ ]$ find ~/ -iname "README.md"
/home/andrew/.jenv/README.md
/home/andrew/.config/micro/plugins/gotham-colors/README.md
/home/andrew/.oh-my-zsh/plugins/ant/README.md
...
findは1971年という最初期のUNIXから実装されているため、1994年にGNUに追加されたlocateより遙かに広い環境で利用可能です。
findはlocateよりずっと多くの機能を備えていて、更新日、サイズ、所有者、ファイル/ディレクトリ、タイムスタンプ、パーミッション、ディレクトリの深さなど多様な条件で検索できます。
またファイル名を正規表現で検索し、見つかったファイルに対してコマンドを実行することもできます。
高速に検索する必要がある場合、また対象ファイルが何処にあるかわからないときはlocateを使用します。
ファイル名以外の何らかの条件に紐付いた正確なファイル一覧が欲しい場合、取得したファイルに対して何かを行いたいときはfindを使用します。
Downloading Things
ping / wget / curl
pingはネットワークホストとの通信を確立しようとします。
主にインターネット接続がダウンしているかどうかを確認するために使用されます。
[ andrew@pc01 ~ ]$ ping google.com
PING google.com (74.125.193.100) 56(84) bytes of data.
Pinging 74.125.193.100 with 32 bytes of data:
Reply from 74.125.193.100: bytes=32 time<1ms TTL=64
...
wgetはインターネットからファイルを簡単にダウンロードできます。
[ andrew@pc01 ~ ]$ wget \
> http://releases.ubuntu.com/18.10/ubuntu-18.10-desktop-amd64.iso
curlもwgetと同じように使用できます。
--outputオプションを忘れないようにしてください。
[ andrew@pc01 ~ ]$ curl \
> http://releases.ubuntu.com/18.10/ubuntu-18.10-desktop-amd64.iso \
> --output ubuntu.iso
curlとwgetには、それぞれ長所と短所があります。
curlはより多くのプロトコルをサポートし、様々な場面で使用可能です。
curlはデータの送信もできますが、wgetは受信しかできません。
wgetはファイルを再帰的にダウンロードできますが、curlはできません。
一般的には、インターネットからファイルをダウンロードするときはwgetを使います。
curlを使ってデータを送信することはあまりありませんが、これを知っておくと、いざ必要になったときに役立ちます。
apt / gunzip / tar / gzip
Debian系のLinuxディストリビューションには、aptという素晴らしいパッケージ管理ツールが存在します。
ソフトウェアのインストール、アップデート、削除が可能です。
何らかのソフトウェアが必要になった場合、apt searchで検索し、apt installでインストールします。
[ andrew@pc01 ~ ]$ apt search bleachbit
...bleachbit/bionic,bionic 2.0-2 all
delete unnecessary files from the system
# インストールにはsudoが必要
[ andrew@pc01 ~ ]$ sudo apt install bleachbit
Linuxのソフトウェアは大抵tarball(.tar.gz)になっています。
[ andrew@pc01 ~ ]$ wget \
> https://github.com/atom/atom/releases/download/v1.35.0-beta0/atom-amd64.tar.gz
この拡張子のファイルはgunzipで解凍できます。
[ andrew@pc01 ~ ]$ gunzip atom-amd64.tar.gz && ls
atom-amd64.tar
.tar.gzファイルをgunzipすると.tarファイルになり、さらにtar -xfで通常のファイルシステムに戻すことができます。
[ andrew@pc01 ~ ]$ tar -xf atom-amd64.tar && mv \
atom-beta-1.35.0-beta0-amd64 atom && ls
atom atom-amd64.tar
逆に圧縮するには、-cでディレクトリから.tarにまとめ、-zで圧縮します。
[ andrew@pc01 ~ ]$ tar -zcf compressed.tar.gz atom && ls
atom atom-amd64.tar compressed.tar.gz
gzipでもファイルを圧縮することができます。
[ andrew@pc01 ~ ]$ gzip atom-amd64.tar && ls
atom atom-amd64.tar.gz compressed.tar.gz
Redirecting Input and Output
| / > / < / echo / printf
デフォルトでは、シェルコマンドは標準入力ストリーム(stdin、0)から入力を読み取り、標準出力ストリーム(stdout、1)に出力を書き込みます。
エラーが発生すると、それは標準エラーストリーム(stderr、2)に出力されます。
echoはデフォルトではstdoutに対してテキストを書き込みます。
ほとんどの環境では、それは単にターミナルに表示される、という意味です。
[ andrew@pc01 ~ ]$ echo "hello"
hello
パイプオペレータ|は、前のコマンドの出力を、後ろのコマンドの入力にリダイレクトします。
# wcはファイルの行数、単語数、バイト数を返すコマンド
[ andrew@pc01 ~ ]$ echo "example document" | wc
1 2 17
>によるリダイレクトは出力先をstdoutから別のものに変更します。
[ andrew@pc01 ~ ]$ echo "test" > file && head file
test
printfはechoの改良版で、フォーマットやエスケープシーケンスが書けます。
[ andrew@pc01 ~ ]$ printf "1\n3\n2"
1
3
2
<はstdinではなく、別のところから入力を取得します。
# sortは入力を行単位でソートするコマンド
[ andrew@pc01 ~ ]$ sort <(printf "1\n3\n2")
1
2
3
ファイルの中身をコマンドに送る推奨された方法は、UUOCではなく<を使うことです。
これを使った場合、データは自然に感じる左から右ではなく、右から左に流れることになるので注意してください。
[ andrew@pc01 ~ ]$ printf "1\n3\n2" > file && sort < file
1
2
3
0 / 1 / 2 / tee
0、1、2は、上記のようにそれぞれ標準入力、標準出力、標準エラーストリームを表します。
各ストリームは前述のように|、<、>各演算子を使ってリダイレクトできますが、それとは別に直接数値で書くこともできます。
その場合、標準出力は>&1、標準エラーは>&2となります。
[ andrew@pc01 ~ ]$ cat test
echo "stdout" >&1
echo "stderr" >&2
デフォルトでは標準出力も標準エラーもターミナルに出力されます。
[ andrew@pc01 ~ ]$ ./test
stderr
stdout
標準入力を/dev/nullに送ると、標準エラーだけがターミナルに表示されます。
[ andrew@pc01 ~ ]$ ./test 1>/dev/null
stderr
標準エラーを/dev/nullに送ると、標準出力だけがターミナルに表示されます。
[ andrew@pc01 ~ ]$ ./test 2>/dev/null
stdout
全てを/dev/nullに送る場合はこうです。
[ andrew@pc01 ~ ]$ ./test &>/dev/null
標準出力の出力先を変更するのではなく、複数の出力先に送りたい場合は、teeコマンドを使います。
[ andrew@pc01 ~ ]$ ls && echo "test" | tee file1 file2 file3 && ls
file0
test
file0 file1 file2 file3
Advanced
Superuser
sudo / su
自分の名前を知りたいときはwhoamiです。
[ andrew@pc01 abc ]$ whoami
andrew
コマンドを別のユーザとして実行したい場合は、sudo -u usernameというコマンドで実行できます。
ただしそのユーザのパスワードが必要です。
[ andrew@pc01 abc ]$ sudo -u test touch def && ls -l
total 0
-rw-r--r-- 1 test test 0 Jan 11 20:05 def
-uを省いた場合のデフォルトはスーパーユーザ、通常はrootであり、このユーザはあらゆる操作が無制限に可能です。
[ andrew@pc01 abc ]$ sudo touch ghi && ls -l
total 0
-rw-r--r-- 1 test test 0 Jan 11 20:05 def
-rw-r--r-- 1 root root 0 Jan 11 20:14 ghi
suで一時的に別のユーザになれます。
戻るときはexitです。
[ andrew@pc01 abc ]$ su test
Password:
test@pc01:/home/andrew/abc$ whoami
test
test@pc01:/home/andrew/abc$ exit
exit
[ andrew@pc01 abc ]$ whoami
andrew
sudoとsuの違いについてもっと知りたい人は、こちらの記事を読みましょう。
!!
スーパーユーザはソフトウェアのインストール、ユーザの作成などを行うことができる唯一のユーザです。
時々それを忘れてエラーを起こすことがあるでしょう。
[ andrew@pc01 ~ ]$ apt install ruby
E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?
頭にsudoをつけてコマンドを再入力するとうまくいきます。
[ andrew@pc01 ~ ]$ sudo apt install ruby
Reading package lists...
!!で同じことができます。
これは前回入力したコマンドを保持しているショートカットです。
[ andrew@pc01 ~ ]$ apt install ruby
E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?
[ andrew@pc01 ~ ]$ sudo !!
sudo apt install ruby
Reading package lists...
デフォルトでは、いちどsudoでコマンド実行に成功すると、その後15分間はパスワード入力なしにsudoコマンドを実行可能です。
15分を超えると、ふたたびパスワードを要求されるようになります。
File Permissions
File Permissions
ファイルに対して読み込み(r)、書き込み(w)、実行(x)の操作をそれぞれ可能だったりできなかったりします。
ファイルへのアクセス権はls -lコマンドで確認することができ、10文字で表されます。
[ andrew@pc01 ~ ]$ ls -lh
total 8
drwxr-xr-x 4 andrew andrew 4.0K Jan 4 19:37 tast
-rwxr-xr-x 1 andrew andrew 40 Jan 11 16:16 test
-rw-r--r-- 1 andrew andrew 0 Jan 11 16:34 tist
各行の最初の文字は、ファイルの種類を表します。
d=ディレクトリ、l=シンボリックリンク、-=通常ファイルなど。
次の3文字はファイルの所有者(u)が持つパーミッション、次の3文字がファイル所有グループ(g)が持つパーミッション、最後の3文字が無関係なユーザ(o)の持つパーミッションです。
rはそのファイルを読み取り可能、wは書き込み可能、xは実行可能であるというパーミッションを表します。
ディレクトリが実行可能であるとは、そのディレクトリの内容を一覧表示できるという意味です。
この3権限のセットを1桁の数値で表すことがよくあります。
xが有効なら1、wが有効なら2、rが有効なら4というふうに2進数として計算します。
例としてr-xであればrとxが有効なので5です。
従って、上記例の3ファイルは順に755、755、644のパーミッションを持つというふうに表されます。
パーミッションの次にある数値は、そのファイルを参照しているリンクの数です。
その次の2つの文字は、それぞれ所有者名と、所有者のグループ名を表します。
今回は所有者もグループも全てandrewです。
さらにその次がファイルのサイズ、更新日時、そして最後にファイル名が表示されます。
lsの-hオプションは人間が読み取りやすいように出力を調整します。
すなわち4096などではなく4.0Kと表示します。
chmod / chown
chmodで数値を与えることにより、ファイルのパーミッションを変更できます。
[ andrew@pc01 ~ ]$ chmod 777 test && chmod 000 tist && ls -lh
total 8.0K
drwxr-xr-x 4 andrew andrew 4.0K Jan 4 19:37 tast
-rwxrwxrwx 1 andrew andrew 40 Jan 11 16:16 test
---------- 1 andrew andrew 0 Jan 11 16:34 tist
あるいはプラスマイナスとrwxで直感的操作もできます。
[ andrew@pc01 ~ ]$ chmod +rwx tist && chmod -w test && ls -lh
chmod: test: new permissions are r-xrwxrwx, not r-xr-xr-x
total 8.0K
drwxr-xr-x 4 andrew andrew 4.0K Jan 4 19:37 tast
-r-xrwxrwx 1 andrew andrew 40 Jan 11 16:16 test
-rwxr-xr-x 1 andrew andrew 0 Jan 11 16:34 tist
ファイルの所有者はchownで変更できます。
[ andrew@pc01 ~ ]$ sudo chown marina test
グループの変更はchgrpです。
[ andrew@pc01 ~ ]$ sudo chgrp hadoop tist && ls -lh
total 8.0K
drwxr-xr-x 4 andrew andrew 4.0K Jan 4 19:37 tast
-----w--w- 1 marina andrew 40 Jan 11 16:16 test
-rwxr-xr-x 1 andrew hadoop 0 Jan 11 16:34 tist
User and Group Management
Users
現在ログインしてる全ユーザの一覧がusersで表示できます。
複数のSSHセッションを張ったりなどで同一ユーザが同時に何度もログインすることができます。
[ andrew@pc01 ~ ]$ users
andrew colin colin colin colin colin krishna krishna
ログインしていないユーザも含め全ユーザを確認するには、/etc/passwdを参照します。
なお、このファイルを変更するとユーザアカウントが破損し、ログインできなくなる可能性があるため、絶対に直接編集しないでください。
[ andrew@pc01 ~ ]$ alias au="cut -d: -f1 /etc/passwd \
> | sort | uniq" && au
_apt
anaid
andrew...
ユーザの追加はuseraddです。
[ andrew@pc01 ~ ]$ sudo useradd aardvark && au
_apt
aardvark
anaid...
ユーザの削除はuserdelです。
[ andrew@pc01 ~ ]$ sudo userdel aardvark && au
_apt
anaid
andrew...
ユーザアカウント操作の詳細についてはこちらを参照してください。
Groups
groupsは、ユーザが属している全てのグループを表示します。
[ andrew@pc01 ~ ]$ groups
andrew adm cdrom sudo dip plugdev lpadmin sambashare hadoop
システム上の全てのグループを確認するには、/etc/groupを参照します。
このファイルを理解していないかぎり、直接変更はしないでください。
[ andrew@pc01 ~ ]$ alias ag=“cut -d: -f1 /etc/group \
> | sort” && ag
adm
anaid
andrew...
グループの追加はgroupaddです。
[ andrew@pc01 ~ ]$ sudo groupadd aardvark && ag
aardvark
adm
anaid...
グループの削除はgroupdelです。
[ andrew@pc01 ~ ]$ sudo groupdel aardvark && ag
adm
anaid
andrew...
グループ操作の詳細についてはこちらを参照してください。
Text Processing
uniq / sort / diff / cmp
uniqコマンドは、連続した重複行を削除して表示します。
[ andrew@pc01 man ]$ printf "1\n2\n2" > a && \> printf "1\n3\n2" > b
[ andrew@pc01 man ]$ uniq a
1
2
sortは行をアルファベット順、もしくは数値順に並び替えます。
[ andrew@pc01 man ]$ sort b
1
2
3
diffは、2つのファイルでどの行が異なるかを表示します。
[ andrew@pc01 man ]$ diff a b
2c2
< 2
---
> 3
cmpは、2つのファイルで最初に異なる場所のバイト数を表示します。
[ andrew@pc01 man ]$ cmp a b
a b differ: char 3, line 2
cut / sed
cutは、文字列をなんらかの区切り文字で分割するコマンドで、CSV処理などに向いています。
-dで区切り文字を指定し、-fは出力するインデックス(1始まり)を指定します。
[ andrew@pc01 man ]$ printf "137.99.234.23" > c
[ andrew@pc01 man ]$ cut -d'.' c -f1
137
sedは、ファイル内の文字列を別の文字列に置換するためによく使われます。
[ andrew@pc01 man ]$ echo "old" | sed s/old/new/
new
実のところsedは非常に強力なユーティリティであり、この狭いスペースでは到底解説することができません。
sedはチューリング完全であり、他のプログラミング言語でできることなら何でもできます。
sedは、正規表現に基づいてテキストを検索・置換し、特定パターンに一致する、あるいは含む行を抽出したり、テキストファイルを非対話式にIn-place編集したり、その他様々なことが行えます。
詳しくは以下のようなチュートリアルを参照してください。
・https://www.tutorialspoint.com/sed/
・http://www.grymoire.com/Unix/Sed.html
・https://www.computerhope.com/unix/used.htm
Pattern Matching
grep
grepの名前はsearch Globally for a Regular Expression and Print itに由来します。
ファイルから、特定のパターンに一致するテキストを見つけるために使用されます。
[ andrew@pc01 ~ ]$ grep -e ".*fi.*" /etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# The file bash.bashrc already sets the default PS1.
fi
fi
...
普通に単語検索もできます。
[ andrew@pc01 ~ ]$ grep "andrew" /etc/passwd
andrew:x:1000:1000:andrew,,,:/home/andrew:/bin/bash
ファイル内の一致する行を見つけた後、他のプログラムでその行を処理させたい場合などに、grepは最適な選択です。
grepでは、正規表現-E、複数文字列のいずれかとマッチさせる-F、ディレクトリ内のファイルを再帰的に検索する-rなどのオプションが存在します。
これらのオプションは元々個別コマンドegrep、fgrep、rgrepとして実装されていましたが、個別コマンドは非推奨になりました。
おまけ
いろいろなコマンド名の由来を見てみよう。
awk
awkは、CSVなどのデリミタで区切られたデータファイルを読み取り、操作することを念頭に作られた言語です。
経験的に、grepはファイルから特定の文字列やパターンを見つけるのに適していて、sedはファイル内の文字列を1対1で置換するのに適しています。
そしてawkは、ファイルからパターンを抽出して分析するのに適しています。
awkができることの例として、2列のデータを含むファイルを処理してみます。
[ andrew@pc01 ~ ]$ printf "A 10\nB 20\nC 60" > file
行ごとにループし、数値を合計し、平均を出力するコードは以下のようになります。
[ andrew@pc01 ~ ]$ awk 'BEGIN {sum=0; count=0; OFS=" "} {sum+=$2; count++} END {print "Average:", sum/count}' file
Average: 30
sedとawkはどちらもチューリング完全な言語です。
これらはパターンマッチングとテキスト処理に非常に役立つ言語で、そしてそれぞれについて書かれた本もたくさんあります。
それらについて書き記すにはここには余白が足りません。
もっと調べてみてください。
Copying Files Over ssh
ssh / scp
sshは、Unixベースのマシン同士がネットワークを介して接続する方法です。
[ andrew@pc01 ~ ]$ ssh –p <port> andrew@137.xxx.xxx.89
Last login: Fri Jan 11 12:30:52 2019 from 137.xxx.xxx.199
別のマシンに入ったのでプロンプトが変わりました。
[ andrew@pc02 ~ ]$ exit
logout
Connection to 137.xxx.xxx.89 closed.
マシン1でファイルを作成します。
[ andrew@pc01 ~ ]$ echo "hello" > hello
これをマシン2にコピーするにはscpコマンドを使用します。
sshはポート番号を-pで指定するのに対し、scpは-Pで指定するのに注意しましょう。
[ andrew@pc01 ~ ]$ scp –P <port> hello andrew@137.xxx.xxx.89:~
hello 100% 0 0.0KB/s 00:00
確認のため、sshでマシン2に入りましょう。
[ andrew@pc02 ~ ]$ ssh –p <port> andrew@137.xxx.xxx.89
Last login: Fri Jan 11 22:47:37 2019 from 137.xxx.xxx.79
そこにファイルが存在しているはずです。
[ andrew@pc02 ~ ]$ ls
hello multi xargs
[ andrew@pc02 ~ ]$ cat hello
hello
rsync
rsyncは、ファイル間の差分を調べることにより、コピーされるデータ量を少なく抑えるファイルコピーツールです。
2つのディレクトリdとsが存在し、dにはファイルがひとつ、sにはふたつ存在するとします。
[ andrew@pc01 d ]$ ls && ls ../s
f0
f0 f1
ディレクトリをrsyncで同期すると、不足しているファイルだけがコピーされます。
[ andrew@pc01 d ]$ rsync -av ../s/* .
sending incremental file list...
最終的にdディレクトリには、sディレクトリに存在する全てのファイルが集まります。
[ andrew@pc01 d ]$ ls
f0 f1
rsyncはssh経由でも実行できます。
[ andrew@pc02 r ]$ ls
[ andrew@pc02 r ]$ rsync -avz -e "ssh -p <port>" andrew@137.xxx.xxx.79:~/s/* .
receiving incremental file list
f0
f1
sent 62 bytes received 150 bytes 141.33 bytes/sec
total size is 0 speedup is 0.00
Long-Running Processes
yes / nohup / ps / kill
ネットワークやハードウェアの問題によって、SSH接続が切断されることがよくあります。
その際、そのSSH接続から起動されていたプロセスには全てHUPシグナルが送られ、プロセスは強制終了されます。
yesコマンドは、停止されるまで"y"を出力し続けます。
これをnohupと一緒に実行しましょう。
[ andrew@pc01 ~ ]$ nohup yes &
[1] 13173
psは、現在のユーザが実行しているプロセスを一覧表示します。
以下の例では、yesコマンドのPIDは13713です。
[ andrew@pc01 ~ ]$ ps | sed -n '/yes/p'
13173 pts/10 00:00:12 yes
ログアウトして再度ログインしてみましょう。
[ andrew@pc01 ~ ]$ ps | sed -n '/yes/p'
表示されなくなりました。
が、実際は裏で実行され続けていてtopやhtopには出てきます。
[ andrew@pc01 ~ ]$ top -bn 1 | sed -n '/yes/p'
13173 andrew 20 0 4372 704 636 D 25.0 0.0 0:35.99 yes
killコマンドに-9オプションを付けて、このプロセスを強制終了しましょう。
[ andrew@pc01 ~ ]$ kill -9 13173
これでプロセスが終了したため、もうtopにも出てきません。
[ andrew@pc01 ~ ]$ top -bn 1 | sed -n '/yes/p'
cron / crontab / >>
cronはタスクを定期的に実行する簡単な方法を提供します。
crontab –eコマンドでテキストエディタが開き、cronを編集することができます。
以下の行を追加しましょう。
* * * * * date >> ~/datefile.txt
毎分dateコマンドを実行し、出力をファイルに保存します。
[ andrew@pc02 ~ ]$ head ~/datefile.txt
Sat Jan 12 14:37:01 GMT 2019
Sat Jan 12 14:38:01 GMT 2019
Sat Jan 12 14:39:01 GMT 2019...
再びcrontabを編集し、該当行を削除すると、このジョブは停止します。
ジョブの頭にある* * * * *は順に分(0-59)、時間(0-23)、日(1-31)、月(1-12)、曜日(0-6もしくはSun-Sat)を表します。
各*を数値に置き換えることで、特定の日や特定の時間にのみジョブを実行することができるようになります。
曜日に関係なくジョブを実行したい場合は、5番目の*を*のままにしておきます。
全ての項目を*にすると毎分実行されるようになり、これが利用可能な最小間隔になります。
システムが再起動されたときだけ実行するように設定することもでき、これは* * * * *のかわりに@rebootと記載します。
また、1時間あるいは一日のうち特定の回数だけ実行するようにしたり、月や曜日や日など複数項目の組み合わせで指定することも可能です。
もっと詳しく知るにはこちらを参照してください。
Miscellaneous
pushd / popd
ディレクトリの移動をスタックするには、cdではなくpushdとpopdを使います。
以下の例ではホームディレクトリから開始します。
[ andrew@pc01 ~ ]$ pwd
/home/andrew
フルパスのpushdでディレクトリを移動します。
[ andrew@pc01 ~ ]$ pushd /etc/java/security/security.d/
/etc/java/security/security.d ~
pushdでサブディレクトリに移動します。
[ andrew@pc01 security.d ]$ pushd ~/test/
~/test /etc/java/security/security.d ~
pushdによって積まれたスタックは、表示の一番左側に追加されます。
popdすると一番最後に追加されたディレクトリに戻ります。
[ andrew@pc01 test ]$ popd
/etc/java/security/security.d ~
[ andrew@pc01 security.d ]$ pwd
/etc/java/security/security.d
何度もpopdすると、最終的にpushdを始めたディレクトリに戻ります。
[ andrew@pc01 security.d ]$ popd
~
xdg-open
xdg-openは、ファイルをデフォルトのアプリケーションで開くコマンドです。
HTMLファイルをブラウザで開きたい場合などに便利です。
MacOSで言うopenコマンドに相当します。
[ andrew@pc01 security.d ]$ xdg-open index.html
xargs
xargs引数のリストに対して、ループ的にコマンドを実行します。
以下はカレントディレクトリ、親ディレクトリ、親の親ディレクトリに対してlsを実行する例です。
[ andrew@pc01 ~ ]$ export lv=".\n..\n../.."
[ andrew@pc01 ~ ]$ printf $lv | xargs ls
.:
multi file
..:
anaid andrew colin...
../..:
bin dev index...
引数は、–Iオプションを使うことで次のコマンドの引数に割り当てることができます。
以下はカレントディレクトリ、親ディレクトリ、親の親ディレクトリに対してcdとpwdを実行する例です。
[ andrew@pc01 ~ ]$ printf $lv | xargs -I % sh -c 'cd %; pwd %'
/home/andrew
/home
/
もっと詳しく知るには、この素晴らしいチュートリアルをご覧ください。
Bonus: Fun-But-Mostly-Useless Things
楽しいけど役に立たないもの。
w / write / wall / lynx
wは誰がログインしていてさらに何をしているかを表示する、whoの詳細版です。
[ andrew@pc01 ~ ]$ w
17:32:42 up 434 days, 3:11, 8 users, load average: 2.32, 2.46, 2.57
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
colin pts/9 137.xx.xx.210 03Jan19 5:28m 1:12 0.00s sshd: colin [priv]
andrew pts/10 137.xx.xx.199 11:05 1.00s 0.15s 0.04s sshd: andrew [priv]
colin pts/12 137.xx.xx.210 03Jan19 34:32 1.59s 1.59s –bash
...
別のユーザに対してwriteでメッセージを送信することができます。
[ andrew@pc01 ~ ]$ echo "hello" | write andrew pts/10
Message from andrew@pc01 on pts/10 at 17:34 ...
hello
EOF
wallはwriteと似ていますが、ログイン中の全ユーザに同じメッセージを送信します。
メールやTwitterやWhatsAppといったアプリが普及する前は、メッセージを送るためにwriteやwallがよく使われていました。
lynxはテキストベースの、完全に機能するWebブラウザです。
nautilus / date / cal / bc
nautilusは新しいセッションを開き、GUIのファイルマネージャをオープンします。
dateは現在の日付と時刻を表示します。
[ andrew@pc01 ~ ]$ date
Fri Jan 11 17:40:30 GMT 2019
calは今月のカレンダーをテキストで表示します。
本日の日付は強調表示されます。
[ andrew@pc01 ~ ]$ cal
January 2019
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
bcは簡易的な電卓です。
かわりにPythonを使いましょう。
[ andrew@pc01 ~ ]$ bc
bc 1.06.95 ...
20/4
5
これでおしまいです!
このリストに追加する必要のある機能や、クールなコマンドを知っていたら教えてください。
またタイプミスや間違いがあったときも教えてください。
ベストを尽くしたつもりですが、きっとたくさんあると思います。
この投稿が参考になったのであれば、ぜひコーヒーを買ってください。
Update 8 July 2019
2年前に書かれた、とてもよく似た記事を発見しました。
フランス語がわかるのであれば、私の記事の補完に最適だと思います。
コメント欄
「素晴らしいポスト!Andrewサンクス!」
「同じ投稿をPowerShellでやってくれたら思い残すことはない。」
「screen。新しいSSH接続を開く。そのセッションはログオフしてもプログラムはずっと実行されたままで、さらに再接続して続きもできる。」「tmuxはいいぞ。screenと似てるけどもっと便利。」
「disown。既に動かした後のプログラムを、後からバックグラウンドに持っていける。」
「ipythonとtrash-cliを是非。」
「date +%sでUNIXタイムを表示できるよ。」
「ncdu初めて知った。これ便利!」
「MacとFreeBSDではtopのユーザ名オプションは-Uだったよ。」
「kill -9はいかん、kill -15か単にkillってするんだ。-15はOSに通知が行く、-9はいきなり電源押して切るようなものだ。」
「sourceとshは同じ結果になることもあるけど全く同じではない。sourceは現在のbash上で実行されてexportした変数も使える。shは新たなシェルを起動するしexportした変数は使えない。」
「bashコマンドって言うけど実際はbashコマンドではなくてUnix/Posixコマンドが多いぞ。」
「xdg-openの画像がWindowsっぽいんだけどどゆこと?」「MobaXTermを使ってWindowsからUbuntuにログインしてるからなのだ。」
「コマンドプロンプトに|を使っててパイプとわかりにくいのでプロンプトは$にしてほしい。」「ありがとう更新したよ!」
「聖なる牛!」
感想
チュートリアル形式でわかりやすい、bashコマンド入門記事です。
最後まで読めばbashスクリプトをバリバリ組めるようなエキスパートになれるかというと怪しいですが、汎用的なbashコマンドについてはひととおり使えるようになっていることでしょう。
LPICのLevel3まで持ってたらよゆーよゆーとか思ってたけど、わりと知らないコマンドも多かった。
知っていると知らないとでは大違いなので、コマンドや機能が存在していることそのものを認識しておくと、今後役に立つことでしょう。
いきなり詳しく知る必要はありません。
詳細は必要になったときにmanなりググるなりすればいいんですよ。
あと原文は、こうすればこうなりますよというのは書かれているんだけど、"何故"そうなるかが書かれていないところがあってちょっと躓く感じがありました。
和訳にあたりそのあたりを一部補完しています。
トップコメのHoly cow!はどう捉えたらいいのかよくわからなかった。

