Linuxコマンドのお勉強 (2)基礎編

もう一度基礎からおさらいしましょう！
# Linux commands (Basic)
## リダイレクト
#### Stdin `<`
(ex.) ファイルを入力リダイレクトして実行

```
$ cat < Package.swift
// swift-tools-version:3.1

import PackageDescription

let package = Package(
name: "NextBrain",
targets: [],
dependencies: [
.Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", versions: Version(1, 0, 0)..<Version(3, .max, .max)),
]
)
```

#### Stdout `>`
*  コマンドラインの実行結果を`sample.txt`に保存
(ex)

```
$ ls -l ~/Desktop > sample.txt
$ cat sample.txt
total 456
drwxr-xr-x@ 10 User  staff     320  7 11 22:45 AirconBeta
drwxr-xr-x   5 User  staff     160  6 23 01:13 HelloWorld
drwxr-xr-x@  8 User  staff     256  6 23 01:24 LabTools
drwxr-xr-x   6 User  staff     192  8  6 21:31 Linux
drwxr-xr-x   9 User  staff     288  6 12 23:29 NextBrain
drwxr-xr-x@ 17 User  staff     544  7 11 22:45 tootyFruity
```
*  StdoutとStderrの分離

(ex. 1) 出力リダイレクトをしてもStderrは表示される(Stderr -> Display かつStderrとStdoutが別のチャネルなため)

```
$ ls /NotExistedDir > notExisted.txt
ls: /NotExistedDir: No such file or directory
```

(ex .2) Stderrのみをファイルに出力 (Stderrのチャネル: 2)

```
$ ls /NotExistedDir 2> notExisted.txt #この時点で出力されない
$ cat notExisted.txt
ls: /NotExistedDir: No such file or directory
```

(ex. 3)  StdoutとStderrをそれぞれ別のファイルに分離する

```
$ ls /NotExistedDir > sample.txt 2> notExisted.txt #Stdout -> sample.txt, Stderr -> notExisted.txt
$ cat sample.txt
$ cat notExisted.txt
ls: /NotExistedDir: No such file or directory
```

(ex. 4) StdoutとStderr (Stdoutのチャネル: 1, *Stdinのチャネル: 0)

```
$ ls /NotExistedDir > sample.txt 2>&1 #  最初の">": Stdout -> sample.txt, "2>&1": Stderr -> Stdout -> sample.txt
$ cat sample.txt
ls: /NotExistedDir: No such file or directory
```

#### Add  `>>`

(ex. 1) `>`でファイルにリダイレクトすると上書きされる

```
$ cat sample.txt
ls: /NotExistedDir: No such file or directory
$ echo 'Overrided!!' > sample.txt
$ cat sample.txt
Overrided!!
```

(ex .2) `>>`で末尾に追記できる

```
$ cat sample.txt
Overrided!!
$ echo 'Add New message' >> sample.txt
$ cat sample.txt
Overrided!!
Add New message
```

## Pipeline `|`

(ex. 1) パイプラインを使わない場合 -> いちいちファイルに出力しなければいけない

```
$ ls ~/Desktop > sample.txt
$ cat sample.txt #この行とこの上の行をパイプラインでまとめられる
AirconBeta
HelloWorld
LabTools
Linux
NextBrain
tootyFruity
```

(ex. 2) (ex. 1)をパイプラインでまとめる

```
$ ls ~/Desktop | cat
AirconBeta
HelloWorld
LabTools
Linux
NextBrain
tootyFruity
```

## フィルタ
#### `head -(n)<行数>`
特に行数を指定しなければ最初の10行を表示する
(ex)

```
$ ls -l | head -2
total 48
-rw-r--r--@ 1 User  staff  10966  8  5 13:54 linuxCommand.md
```

#### `du [オプション] <ファイル/Dir>`
* `info du`: `du`コマンドの情報を見る

(ex. 1)  ディレクトリ内の全ファイルのサイズを表示する

```
$ du -a -h
8.0K    ./.DS_Store
4.0K    ./notExisted.txt
4.0K    ./linuxCommnadNormal.md
12K    ./linuxCommand.md
4.0K    ./sample.txt
32K    .
```

(ex. 2) ディレクトリ内の全ファイルをサイズの小さい順に表示する

```
$ du -a -h | sort -n
4.0K    ./linuxCommnadNormal.md
4.0K    ./notExisted.txt
4.0K    ./sample.txt
8.0K    ./.DS_Store
12K    ./linuxCommand.md
32K    .
```

(ex .3) ディレクトリ内の全ファイルをサイズの大きい順に表示する (敢えて`sort -r`とはせずに`tac`を利用)

```
$ alias tac='tail -r' #macにはtacがないのでエイリアスをあらかじめ設定
$ du -a -h | sort -n | tac
32K    .
12K    ./linuxCommand.md
8.0K    ./.DS_Store
4.0K    ./sample.txt
4.0K    ./notExisted.txt
4.0K    ./linuxCommnadNormal.md
```

(ex. 4) ファイルサイズの大きい上位3つを表示

```
$ du -a -h | sort -n | tac | head -3
32K    .
12K    ./linuxCommand.md
8.0K    ./.DS_Store
```

#### `wc [オプション] <ファイル名>`
入力ファイルの行数・単語数・バイト数を数える
(ex. 1)

```
$ wc linuxCommand.md
253     759   10966 linuxCommand.md #行数(-l) 単語数(-w) バイト数(-c) ファイル名 で表示
```

* `wc -l`: 行数
* `wc -w`: 単語数
* `wc -c`: バイト数

(ex. 2) ホームディレクトリ直下のファイル及びディレクトリ数をカウント

```
$ ls ~/ | wc -l #ls ~/でのStdoutがそのまま渡されるためこのように利用できる.またwcはファイル名を指定していないとデフォルトでStdinから読み込む(明示的に読み込む場合は"-"を指定する)
13
```

#### `sort [オプション] <ファイル名>`
以下のファイルを用意
```sample. txt
Swift
Ruby
Python
Java
Javascript
Coffeescript
C
R
```

(ex. 1) `sort`: デフォルトでは辞書順で出力

```
$ sort sample.txt
C
Coffeescript
Java
Javascript
Python
R
Ruby
Swift
```

(ex .2) `sort -r`: 逆順にソート

```
$ sort -r sample.txt
Swift
Ruby
R
Python
Javascript
Java
Coffeescript
C
```

(ex .3) `sort -k <フィールド番号>`: <フィールド番号>の部分を対象に並べ替え

```
$ ps -x | sort -k 5 | head -3
287 ??         0:20.13 /usr/libexec/lsd
289 ??         0:53.87 /System/Library/CoreServices/Dock.app/Contents/MacOS/Dock
290 ??         0:06.44 /System/Library/CoreServices/talagent
```

なお，/usr... の後に /System... がきているのは`sort`がASCIIコード順にソートすることによる(ASCIIコードでは大文字<小文字.例えば"A"は65，"a"は97)

(ex. 4) `sort -n`: 数値とみなして並べ替え
以下のファイルを用意

```numberSample.txt
5
9
10
1
3
2
22
28
13
4
```
文字列で並び替えるうまくいかない

```
$ sort numberSample.txt
1
10
13
2
22
28
3
4
5
9
```

数値とみなすとうまくいく

```
$ sort -n numberSample.txt
1
2
3
4
5
9
10
13
22
28
```

(ex. 5) ファイルサイズの大きい順にファイルを表示

```
$ ls -l ~/Desktop | sort -rn -k 5
drwxr-xr-x@ 17 User  staff  544  7 11 22:45 tootyFruity
drwxr-xr-x@ 10 User  staff  320  7 11 22:45 AirconBeta
drwxr-xr-x   9 User  staff  288  6 12 23:29 NextBrain
drwxr-xr-x@  8 User  staff  256  6 23 01:24 LabTools
drwxr-xr-x   8 User  staff  256  8  7 00:24 Linux
drwxr-xr-x   5 User  staff  160  6 23 01:13 HelloWorld
total 0
```

(ex. 6) `sort -u`: 重複行を取り除く
以下のファイルを用意

```sample.txt
Swift
Ruby
Python
Java
Javascript
Coffeescript
C
Swift
R
```
上記ファイルに対し`sort -u`を実行

```
$ sort -u sample.txt
C
Coffeescript
Java
Javascript
Python
R
Ruby
Swift
```

#### `uniq [オプション] <ファイル名>`
**連続した**同じ内容の行を取り除く．以下のファイルを用意

```uniq.txt
Swift
Swift
Ruby
Python
Java
Javascript
Coffeescript
C
R
```

(ex .1) `uniq`: 同じ行が連続している場合重複を取り除いて出力

```
$ uniq uniq.txt
Swift
Ruby
Python
Java
Javascript
Coffeescript
C
R
```

同じ行が重複していないと意味がない

```
$ uniq uniq2.txt
Swift #ココと
Ruby
Python
Java
Javascript
Coffeescript
C
Swift #ココ
R
```

この場合は`sort`で並べ替えてから`uniq`すれば良い

```
$ sort uniq2.txt | uniq
C
Coffeescript
Java
Javascript
Python
R
Ruby
Swift
```

*上述の`sort -u`も使える

(ex. 2) `uniq -c`: 重複行数を数える
以下のファイルを用意

```uniq3.txt
Swift
Ruby
Python
Java
Javascript
Coffeescript
C
Swift
R
Ruby
Swift
Ruby
Java
```

(ex. 1)同様に連続していないと抜き出せない

```
$ uniq -c uniq3.txt
1 Swift
1 Ruby
1 Python
1 Java
1 Javascript
1 Coffeescript
1 C
1 Swift
1 R
1 Ruby
1 Swift
1 Ruby
1 Java
```

`sort`と組み合わせる

```
$ sort uniq3.txt | uniq -c
1 C
1 Coffeescript
2 Java
1 Javascript
1 Python
1 R
3 Ruby
3 Swift
```

さらに重複行の多い順に表示

```
$ sort uniq3.txt | uniq -c | sort -rn
3 Swift
3 Ruby
2 Java
1 R
1 Python
1 Javascript
1 Coffeescript
1 C
```

#### `cut -d <区切り文字> -f <フィールド番号> <ファイル名>`
\*`-d`を指定しないとデフォルトでは**タブ**が区切り文字としてみなされる

(ex) "/"で分けて見る

```
$ ps x | head -8 | cut -d / -f 2
PID   TT  STAT      TIME COMMAND
usr
usr
usr
System
usr
usr
System
```

`-f`は複数指定もできる．↓のは上における"usr"などが消えていることがわかる

```
$ ps x | head -8 | cut -d / -f 1,3,4
PID   TT  STAT      TIME COMMAND
275   ??  S      0:51.07 /sbin/cfprefsd agent
280   ??  S      0:17.34 /libexec/UserEventAgent (Aqua)
282   ??  S      2:08.86 /sbin/distnoted agent
284   ??  S      0:34.93 /Library/Frameworks
286   ??  S     21:21.97 /libexec/trustd --agent
287   ??  S      0:20.71 /libexec/lsd
289   ??  S      0:58.41 /Library/CoreServices
```

#### `tr <置換前の文字> <置換後の文字>`
(ex .1) "/"を":"に置換する

```
$ ps x | head -3 | tr / :
PID   TT  STAT      TIME COMMAND
275   ??  S      0:51.26 :usr:sbin:cfprefsd agent
280   ??  S      0:17.43 :usr:libexec:UserEventAgent (Aqua)
```

(ex .2) 複数の文字を置換する

```
$ ps x | head -3 | tr usr USR
PID   TT  STAT      TIME COMMAND
275   ??  S      0:51.31 /USR/Sbin/cfpRefSd agent
280   ??  S      0:17.44 /USR/libexec/USeREventAgent (AqUa)
```

(ex .3) 文字範囲を指定して置換する

```
$ ps x | head -3 | tr a-z A-Z
PID   TT  STAT      TIME COMMAND
275   ??  S      0:51.34 /USR/SBIN/CFPREFSD AGENT
280   ??  S      0:17.45 /USR/LIBEXEC/USEREVENTAGENT (AQUA)
```

(ex. 4) ファイル指定をすると実行できないので注意(`cat`でパイプを通すか、入力リダイレクトを用いる)

```
$ tr A-Z a-z sample.txt
usage: tr [-Ccsu] string1 string2
tr [-Ccu] -d string1
tr [-Ccu] -s string1
tr [-Ccu] -ds string1 string2
```

入力リダイレクトを用いると以下のように実行できる

```
$ tr A-Z a-z < sample.txt
swift
ruby
python
java
javascript
coffeescript
c
r
```

(ex. 5) `tr -d <削除文字>`

```
$ ps x | head -3 | tr -d "\n"
PID   TT  STAT      TIME COMMAND  275   ??  S      0:51.52 /usr/sbin/cfprefsd agent  280   ??  S      0:17.49 /usr/libexec/UserEventAgent (Aqua) #以下省略
```

#### `tail <オプション> <ファイル名>`
`head`の逆で、末尾を表示する．<オプション>を指定しないと末尾10行を表示する．

(ex .1) `tail -(n)<表示したい行数>`

```
$ ps x | tail -3
53224 s000  S      0:00.42 -bash
54476 s000  R+     0:00.00 ps x
54477 s000  S+     0:00.00 tail -3
```

(ex .2) `tail -f`: ファイルへの追記を監視
以下の状態で一旦止まる

```
$ touch tailF.txt
$ tail -f tailF.txt
```

別画面上で`$ echo 'Watch tailF.txt' > tailF.txt`を実行すると

```
$ tail -f tailF.txt
Watch tailF.txt
```
となる．(Ctrl + cで終了)