知ってたら少し幸せになれるshellコマンドのオプションたち

### はじめに
コマンドのオプションってたくさんありますよね。
コマンドのオプションを知ったら楽になるかも？と思ってオプションを調べました。
その中で頻繁に使う基本的なコマンドで、使えそうなオプションをまとめました。

### 動作環境
動作確認環境はAmazonLixun2のBashです。

```bash
$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
$ bash --version
GNU bash, バージョン 4.2.46(2)-release (x86_64-koji-linux-gnu)
```


### ls
おなじみls。lsの意味は`list segments`らしいです。ずっと`list`だと思っていました。

- オプション無しで実行

```
[user@server ~]$ ls
dir1   file1  file2  file3  file4  file
```

- `ls -l` : 詳細を出力

```
[user@server ~]$ ls -l
合計 20
drwxrwxr-x 2 user user  6  8月 11 18:42 dir
-rw-rw-r-- 1 user user 13  8月  5 18:00 file1
-rw-rw-r-- 1 user user 15  8月  6 18:30 file2
-rw-rw-r-- 1 user user 26  8月  7 10:30 file3
-rw-rw-r-- 1 user user 71  8月  8 12:30 file4
-rw-rw-r-- 1 user user 47  8月  9 15:30 file5
```


- `ls -—full-time` : 更新時間をナノ秒まで出力
- `ls -t` : ファイルの新しい時間順で出力
- `ls -tr` : ファイルの古い時間順で出力

```
[user@server ~]$ ls --full-time -t
合計 20
drwxrwxr-x 2 user user  6 2021-08-11 18:42:31.614583205 +0900 dir
-rw-rw-r-- 1 user user 47 2021-08-09 15:30:00.000000000 +0900 file5
-rw-rw-r-- 1 user user 71 2021-08-08 12:30:00.000000000 +0900 file4
-rw-rw-r-- 1 user user 26 2021-08-07 10:30:45.000000000 +0900 file3
-rw-rw-r-- 1 user user 15 2021-08-06 18:30:36.000000000 +0900 file2
-rw-rw-r-- 1 user user 13 2021-08-05 18:00:11.000000000 +0900 file1
[user@server ~]$ ls --full-time -tr
合計 20
-rw-rw-r-- 1 user user 13 2021-08-05 18:00:11.000000000 +0900 file1
-rw-rw-r-- 1 user user 15 2021-08-06 18:30:36.000000000 +0900 file2
-rw-rw-r-- 1 user user 26 2021-08-07 10:30:45.000000000 +0900 file3
-rw-rw-r-- 1 user user 71 2021-08-08 12:30:00.000000000 +0900 file4
-rw-rw-r-- 1 user user 47 2021-08-09 15:30:00.000000000 +0900 file5
drwxrwxr-x 2 user user  6 2021-08-11 18:42:31.614583205 +0900 dir
```


- `ls -S` : サイズ順で出力
- `ls -p` : ディレクトリ名の後ろに"/"を着けて出力

```
[user@server ~]$ ls --full-time -Sp
合計 20
-rw-rw-r-- 1 user user 71 2021-08-08 12:30:00.000000000 +0900 file4
-rw-rw-r-- 1 user user 47 2021-08-09 15:30:00.000000000 +0900 file5
-rw-rw-r-- 1 user user 26 2021-08-07 10:30:45.000000000 +0900 file3
-rw-rw-r-- 1 user user 15 2021-08-06 18:30:36.000000000 +0900 file2
-rw-rw-r-- 1 user user 13 2021-08-05 18:00:11.000000000 +0900 file1
drwxrwxr-x 2 user user  6 2021-08-11 18:42:31.614583205 +0900 dir/
```

### cd 
これもおなじみchange directoryですね。

- `cd -` :一つ前のディレクトリに戻る。(正確には - はオプションではありません)

```
[user@server ~]$ cd work/
[user@server work]$ cd -
/home/user
[user@server ~]$ cd -
/home/user/work
[user@server work]$ pwd 
/home/user/work
```

地味に役に立つので結構使います。
pushdやpopdでも良いかもしれません。自分はpushして何番目かわからなくなるのでpushは諦めました...

### echo
文字列を標準出力に出力するものですね。

- オプション無しで実行  

```
[user@server ~]$ echo "hogehogeeeee"
hogehogeeeee
[user@server ~]$ echo "hogehog\neeeee"
hogehog\neeeee
```


- `echo -n` : 最後の改行を出力しない

```
[user@server ~]$ echo  -n "hogehogeeeee"
hogehogeeeee[user@server ~]$
```

- `echo -e` : \でエスケープした文字を解釈

```
[user@server ~]$  echo  -e  "hogehog\neeeee"
hogehog
eeeee
```
→例えば\nを改行としてとして出力するようになります。


※使い道はないと思いますが -nと-eを組み合わせるとこんな事もできます。

```
[user@server ~]$ echo  -en "hogehogeeeee\n"
hogehogeeeee
```
改行出すのかい。出さないのかいどっちなんだい！となかやまきんに君状態になれます。


### grep
検索文字列に一致する行を出力するコマンドですね。

- コマンド実行前の状態

```
[user@server ~]$ ls -1
dir
file1
file2
file3
file4
file5
[user@server ~]$ head file*
==> file1 <==
hogehogehoge
fugafugafuga
piyopiyopiyo
foo
bar
baz

==> file2 <==
fuga

==> file3 <==
piyo

==> file4 <==
power

==> file5 <==
bar
```

- オプション無しで実行  

```
[user@server ~]$  grep  piyo ./file*
./file1:piyopiyopiyo
./file3:piyo
```

- `grep -l` : ヒットしたファイル名のみ出力

```
[user@server ~]$  grep -l  piyo ./file*
./file1
./file3
```

- `grep -A [num]` : 検索文字列と一致した後の行も含めてを出力 
- `grep -B [num]` : 検索文字列と一致した前の行も含めてを出力 
- `grep -C [num]` : 検索文字列と一致した前後の行を出力(`-C 2` と `-A 2 -B 2` と同じ)

```
[user@server ~]$ grep -A 2 piyo file*
file1:piyopiyopiyo
file1-foo
file1-bar
--
file3:piyo
[user@server ~]$ grep -A 2 piyopiyo file*
file1:piyopiyopiyo
file1-foo
file1-bar
[user@server ~]$ grep -B 2 piyopiyo file*
file1-hogehogehoge
file1-fugafugafuga
file1:piyopiyopiyo
[user@server ~]$ grep -C 2 piyopiyo file*
file1-hogehogehoge
file1-fugafugafuga
file1:piyopiyopiyo
file1-foo
file1-bar
```

- `grep –L` : 検索した結果該当しなかったファイルを出力

```
[user@server ~]$ grep -L piyopiyo file*
file2
file3
file4
file5
```

- `grep -s` : 標準エラー出力を出力しない (2>/dev/nullの代わり）

```
[user@server ~]$ grep  fuga *
grep: dir: Is a directory
file1:fugafugafuga
file2:fuga
[user@server ~]$ grep -s fuga *
file1:fugafugafuga
file2:fuga
[user@server ~]
```
`Is a directory`など頻繁に出力されるものが消えるので地味に便利です。


### cat 
ファイルの内容を連結して標準出力に出力するものですね。
concatrateの意味で覚えていましたが、catenateという意味もあることを今回知りました。

- オプション無しで実行  

```
[user@server ~]$ cat file1
hogehogehoge
piyopiyo
foo



bar

baz

```

- `cat -n` : 行番号をつける
- `cat -E` : 行の最後に$をつける

```
[user@server ~]$ cat -nE file1
     1  hogehogehoge$
     2  piyopiyo$
     3  foo$
     4  $
     5  $
     6  $
     7  bar$
     8  $
     9  baz$
    10  $
```

- `cat -s` 連続した空行は1行の空行として出力

```
[user@server ~]$ cat -nEs file1
     1  hogehogehoge$
     2  piyopiyo$
     3  foo$
     4  $
     5  bar$
     6  $
     7  baz$
     8  $
```


### mv/cp

`cp`はファイル/やディレクトリのコピー、`mv`はファイルやディレクトリを移動するコマンドですね。
うっかり上書きしてしまうこともしばしば...
※サンプルはmvで行っていますが、今回紹介するオプションはcpでも使うことができます。


- `mv -i` : 上書きの前に確認、yを入力するとファイル移動して既存ファイルを上書き

```
[user@server ~]$ head file1 dir/file1
==> file1 <==
hogehogehoge

==> dir/file1 <==
hogehogehoge
fuga

[user@server ~]$ mv -i file1 dir/file1
mv: `dir/file1' を上書きしますか? 
[user@server ~]$ head file1 dir/file1
==> file1 <==
hogehogehoge

==> dir/file1 <==
hogehogehoge
fuga

[user@server ~]$ mv -i file1 dir/file1
mv: `dir/file1' を上書きしますか? y
[user@server ~]$ head file1 dir/file1
head: `file1' を 読み込み用に開くことが出来ません: No such file or directory
==> dir/file1 <==
hogehogehoge
```


- `mv -n` : 移動先にファイルが存在する場合、ファイルを移動しない

```
[user@server ~]$ head file1 dir/file1
==> file1 <==
hogehogehoge

==> dir/file1 <==
hogehogehoge
fuga

[user@server ~]$ mv -n file1 dir/file1
[user@server ~]$ head file1 dir/file1
==> file1 <==
hogehogehoge

==> dir/file1 <==
hogehogehoge
fuga
```

- `mv -u` : 移動先にファイルが存在する場合し、移動先のファイルより古い場合はファイルを移動しない

```
[user@server ~]$ ls -lr *
-rw-rw-r-- 1 user user  4  8月 13 13:32 file5
-rw-rw-r-- 1 user user  6  8月 13 13:32 file4
-rw-rw-r-- 1 user user  5  8月 13 13:31 file3
-rw-rw-r-- 1 user user  5  8月 13 13:31 file2
-rw-rw-r-- 1 user user 13  8月 17 13:42 file1
[user@server ~]$ head file1 file2
==> file1 <==
hogehogehoge

==> file2 <==
fugafuga
[user@server ~]$ mv -n file2 file1 
[user@server ~]$ head file1 file2
==> dir/file1 <==
hogehogehoge

==> file2 <==
fugafuga
[user@server ~]$ mv -n file1 file2 
[user@server ~]$ head file1 file2
head: `file1' を 読み込み用に開くことが出来ません: No such file or directory
==> file2 <==
hogehogehoge
```

- `mv -b` : 上書きするファイルがある際にバックアップを作成
- `mv -S [str]` :  バックアップファイルのファイル名末尾(接尾辞)を変更

```
[user@server ~]$ ls -lr *
-rw-rw-r-- 1 user user  4  8月 13 13:32 file5
-rw-rw-r-- 1 user user  6  8月 13 13:32 file4
-rw-rw-r-- 1 user user  5  8月 13 13:31 file3
-rw-rw-r-- 1 user user  5  8月 13 13:31 file2
-rw-rw-r-- 1 user user 22  8月 17 13:44 file1

dir:
合計 4
-rw-rw-r-- 1 user user 13  8月 17 13:42 file1
[user@server ~]$ head   file1 dir/file1*
==> file1 <==
hogehogehoge
piyopiyo

==> dir/file1 <==
hogehogehoge
[user@server ~]$ mv -b -S _backup file1 dir/file1
[user@server ~]$ head   file1 dir/file1*
head: `file1' を 読み込み用に開くことが出来ません: No such file or directory
==> dir/file1 <==
hogehogehoge
piyopiyo

==> dir/file1_backup <==
hogehogehoge
```

### xargs
標準入力を読み込み、xargsで指定するコマンドの引数として実行するものですね。

- オプション無しで実行  

```
[user@server ~]$ grep -ls fuga ./* | xargs cat
fuga
```

- `xargs -I{}`　: {}で指定した箇所を、標準入力から読み込んだ値で置き換え

```
[user@server ~]$ grep -ls fuga ./*
./file2

grep -l fuga ./* | xargs -I{} cp {} file_include_fuga

[user@server ~]$ grep -ls fuga ./*
./file2
./file_include_fuga
```

- `xargs -p` : コマンドに実行する前に確認、yを押すと実行

```
[user@server ~]$ grep -ls fuga ./* | xargs -pI{}  cp {} file_include_fuga
cp ./file2 file_include_fuga ?...
```

- `xargs -t` : 実行したコマンドを標準エラーに出力

```
[user@server ~]$ grep -ls fuga ./* | xargs -tI{}  cp {} file_include_fuga 2> std_err
[user@server ~]$ cat std_err
cp ./file2 file_include_fuga
```




### 終わりに

ココで紹介したオプションはほんの少しです。
まだまだオプションはたくさんあるので、是非他のオプションも調べてみてください！