Linux - ファイル検索方法(locate find xargs)徹底的に覚えましょう

### Linux ファイル検索

#### 内容概要
- locate
- find
- xargs

#### 1. ファイル検索
ファイルシステム上で条件に合致するファイルを検索する方法には、次の二つがあります。

- **非リアルタイム検索（データベース検索）**：`locate`
- **リアルタイム検索**：`find`

##### 1.1 locate
`locate` コマンドは、システムに事前に作成されたファイル索引データベース `/var/lib/mlocate/mlocate.db` を検索します。  
索引はシステムが比較的アイドル状態の時に自動的に構築される（周期タスク）。データベースの更新は `update` コマンドで行います。  
索引を作成する過程では、ルートファイルシステム全体をトラバースする必要があり、リソースを大量に消費します。  
`locate` および `update` コマンドは `mlocate` パッケージに含まれています。

###### 特徴：
- 検索速度が速い
- 曖昧検索が可能
- 非リアルタイム検索
- ファイルの完全なパスを検索対象とする
- 読み取りおよび実行権限があるディレクトリのみを検索可能

###### インストール方法：
```shell
# RHEL系
yum install -y mlocate
# Ubuntu系
apt install -y mlocate
```

###### 使用法：
```shell
locate [OPTION]... [PATTERN]...
```

###### オプション：
- `-A`, `--all` : 一致した全てのファイル名を出力（ファイルの存在有無に関わらず）
- `-b`, `--basename` : ファイル名のみをマッチ対象とし、パス内の内容は無視
- `-c`, `--count` : 見つかったファイルの数のみを出力
- `-d`, `--database DBPATH` : データベースのパスを指定
- `-e`, `--existing` : 存在するファイルのエントリのみを出力
- `-L`, `--follow` : ソフトリンクに遭遇した場合、リンク先のファイルを検索（デフォルト）
- `-i`, `--ignore-case` : 大文字小文字を区別しない
- `-l`, `--limit`, `-n N` : 最初のN個のマッチデータのみを表示
- `-P`, `--nofollow`, `-H` : ソフトリンクを追跡しない
- `-q`, `--quiet` : エラーメッセージを出力しない
- `-r`, `--regexp REGEXP` : 基本正規表現を使用
- `--regex` : 拡張正規表現を使用
- `-s`, `--stdio` : 後方互換性を無視
- `-w`, `--wholename` : キーワードがパス内に出現する場合は全パスをマッチ対象とする（デフォルト）

###### 例1 - データベースの作成：
```shell
[root@rocky8 ~]# dnf -y install mlocate
[root@rocky86 ~]# locate conf
locate: can not stat () `/var/lib/mlocate/mlocate.db': No such file or directory
[root@rocky8 ~]# updatedb
[root@rocky8 ~]# ll /var/lib/mlocate/mlocate.db
-rw-r----- 1 root slocate 3143608 Jun 18 08:58 /var/lib/mlocate/mlocate.db
[root@rocky8 ~]# locate -n 3 conf
/boot/config-4.18.0-348.el8.0.2.x86_64
/boot/grub2/i386-pc/configfile.mod
/boot/loader/entries/c0298860b41f4cd296da0d2853451604-0-rescue.conf
```

###### 例2 - ファイルが新規作成および削除
```shell
#検索データベースをすぐに更新できません
[root@rocky86 ~]# touch test.log
[root@rocky86 ~]# locate test.log
#データベースを更新してから再度検索
[root@rocky86 ~]# updatedb
[root@rocky86 ~]# locate test.log
/root/test.log
#ファイルは削除されましたが、まだ見つかります
[root@rocky86 ~]# rm -f test.log
[root@rocky86 ~]# locate test.log
/root/test.log
#実際にはファイルはもう存在しません
[root@rocky86 ~]# stat /root/test.log
stat: cannot statx '/root/test.log': No such file or directory
#データベースを再度更新します
[root@rocky86 ~]# updatedb
[root@rocky86 ~]# locate test.log
[root@rocky86 ~]#
```

###### 例3 - 内容検索
```shell
#名前またはパスに「conf」を含むファイルを検索する
[root@rocky86 ~]# locate conf
#ect ディレクトリ内で a で始まるファイルまたはディレクトリを検索します
[root@rocky86 ~]# locate /etc/a
#ファイル名に share を含むコンテンツのみを検索します
[root@rocky86 ~]# locate -b share
#表示数量
[root@rocky86 ~]# locate -c conf
#最初の 10 件を表示
[root@rocky86 ~]# locate -n 10 conf
#正規表現を使用する
[root@rocky86 ~]# locate -r '\.conf$'
#データベースの指定
[root@rocky86 ~]# locate -d /tmp/nofile conf
locate: can not stat () `/tmp/nofile': No such file or directory
#Quiet モード、エラー メッセージは出力されません
[root@rocky86 ~]# locate -qd /tmp/nofile conf
```

## 1.2 find

**find** はリアルタイムでファイルを検索するツールで、指定されたパスをトラバースしてファイル検索を行います。

### 工作特点：
- 検索速度はやや遅い
- 精確な検索
- リアルタイム検索
- 豊富な検索条件
- 読取り及び実行権限があるディレクトリのみ検索する可能性があります

### フォーマット：
```shell
# find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec][path...] [expression]
find [OPTION]... [検索パス] [検索条件] [処理アクション]
```

#### 検索パス：
具体的なターゲットパスを指定します。デフォルトは現在のディレクトリです。

#### 検索条件：
ファイル名、サイズ、タイプ、パーミッションなどの基準を指定します。デフォルトでは指定したパス下のすべてのファイルが見つかります。

#### 処理動作：
条件に合致するファイルに対する操作です。デフォルトは画面への出力です。

#### 例 - デフォルトでは現在のディレクトリ下のすべてのファイルを列挙します:
```shell
[root@rocky86 0723]# find
.
./dir1
./dir1/dir2
./dir1/dir2/dir3
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy
./dir1/dir2/fa
./dir1/dir2/fb
./dir1/f1
./dir1/f2
./fstab
./.issue
```

### 1.2.1 指定検索ディレクトリ階層
`-maxdepth N` # 最大検索ディレクトリ深度、指定ディレクトリ下のファイルは第1階層とします
`-mindepth N` # 最小検索ディレクトリ深度

#### 例：
##### 最大検索深度
```shell
[root@rocky86 ~]# find /etc/ -maxdepth 2
```
##### 最小検索深度
```shell
[root@rocky86 ~]# find /etc/ -mindepth 2
```
##### 第二階層ディレクトリのみ検索
```shell
[root@rocky86 ~]# find /etc/ -maxdepth 2 -mindepth 2
```

### 1.2.2 ファイルを先に処理してからディレクトリを処理
`-depth` # ファイルを先に処理します

#### 例:
```shell
[root@rocky86 0723]# tree -a
.
├── dir1
│ ├── dir2
│ │ ├── dir3
│ │ │ ├── fx
│ │ │ └── fy
│ │ ├── fa
│ │ └── fb
│ ├── f1
│ └── f2
├── fstab
└── .issue
3 directories, 8 files
# デフォルトで先にディレクトリを表示
[root@rocky86 0723]# find
.
./dir1
./dir1/dir2
./dir1/dir2/dir3
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy
./dir1/dir2/fa
./dir1/dir2/fb
./dir1/f1
./dir1/f2
./fstab
./.issue
# ファイルを先に表示
[root@rocky86 0723]# find -depth
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy
./dir1/dir2/dir3
./dir1/dir2/fa
./dir1/dir2/fb
./dir1/dir2
./dir1/f1
./dir1/f2
./dir1
./fstab
./.issue
```

### 1.2.3 ファイル名とinodeで検索
- `-name name` # グロブを使用して検索、例: `*`, `?`, `[]`, `[^]`。ワイルドカードはダブルクォートで囲む必要があります。
- `-iname name` # 大文字小文字を区別せずに検索
- `-inum number` # inode番号で検索
- `-samefile name` # 同じinode番号を持つファイルを検索
- `-links n` # リンク数がnのファイルを検索
- `-regex "PATTERN"` # PATTERNで全ファイルパスをマッチング（ファイル名ではない）

#### 例：
##### ディレクトリ内容を表示
```shell
[root@rocky86 0723]# ls
dir1 fstab test-a.log test-A.log test-a.txt test-A.txt test-b.log test-B.log test-b.txt test-B.txt
```
##### 指定ファイル名で検索
```shell
[root@rocky86 0723]# find -name test-a.log
./test-a.log
```
##### 指定ファイル名で検索（大文字小文字を区別しない）
```shell
[root@rocky86 0723]# find -iname test-a.log
./test-a.log
./test-A.log
```
##### ワイルドカード
```shell
[root@rocky86 0723]# find -name "*txt"
./test-a.txt
./test-b.txt
./test-A.txt
./test-B.txt
```
##### ワイルドカード
```shell
[root@rocky86 0723]# find -name "test-a*"
./test-a.log
./test-a.txt
```
##### 正規表現で検索（.logで終わる）
```shell
[root@rocky86 0723]# find -regex ".*\.log$"
./test-a.log
./test-b.log
./test-A.log
./test-B.log
```
##### 正規表現で検索（test-[a-z]を含む）
```shell
[root@rocky86 0723]# find -regex ".*test-[a-z].*"
./test-a.log
./test-a.txt
./test-b.log
./test-b.txt
```
##### 正規表現でパスをマッチング
```shell
[root@rocky86 0723]# find -regex ".*dir3.*"
./dir1/dir2/dir3
./dir1/dir2/dir3/fx
./dir1/dir2/dir3/fy
```
##### 正規表現でパスをマッチング（dir3で終わる）
```shell
[root@rocky86 0723]# find -regex ".*dir3$"
./dir1/dir2/dir3
```

### 1.2.5 ファイルタイプに基づいて検索
`-type TYPE` # 指定したファイルタイプで検索します
#### type の値
- `f` # 通常のファイル
- `d` # ディレクトリファイル
- `l` # シンボリックリンクファイル
- `s` # ソケットファイル
- `b` # ブロックデバイスファイル
- `c` # キャラクターデバイスファイル
- `p` # パイプファイル

#### 例：
##### 現在のディレクトリ下のすべてのディレクトリファイルを表示
```shell
[root@rocky86 0723]# find -type d
.
./dir1
./dir1/dir2
./dir1/dir2/dir3
```
##### /run ディレクトリ下のすべてのパイプファイルを検索
```shell
[root@rocky86 0723]# find /run/ -type p
```

### 1.2.6 空のファイルまたはディレクトリ
`-empty` # 空のファイルまたはディレクトリ

#### 例：
##### 空のファイルまたはディレクトリ
```shell
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy
dir1/dir2/dir3/dir4
```
##### 空のディレクトリを検索
```shell
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty -type d
dir1/dir2/dir3/dir4
```
##### 空のファイルを検索
```shell
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty -type f
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy
```

### 1.2.7 条件の組み合わせ
`-a` # そして（デフォルト）
`-o` # または
`-not`, `!` # ではない

#### 例：
##### 既定は `-a`、省略可
```shell
[root@rocky86 0723]# find -name "*log" -a -type f
./test-a.log
./test-b.log
./test-A.log
./test-B.log
```
##### または
```shell
[root@rocky86 0723]# find -name "test*log" -o -name "test*txt"
./test-a.log
./test-a.txt
./test-b.log
./test-b.txt
```
##### ではない
```shell
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty -not -type d
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy
```
##### ではない（別の記述方法）
```shell
[root@rocky86 0723]# find dir1/dir2/dir3/ -empty ! -type d
dir1/dir2/dir3/fx
dir1/dir2/dir3/fy
```

### 1.2.8 ディレクトリを除外して検索
`-prune` # 指定されたディレクトリをスキップして除外します。`-path` と組み合わせて使用する必要があります。

#### 例：
##### すべてのtxtファイルを検索
```shell
[root@rocky86 0723]# find -name "*.txt"
./dir1/fa.txt
./dir1/fb.txt
./test-a.txt
./test-b.txt
./dir4/f-x.txt
./dir4/f-y.txt
```
##### dir1ディレクトリのtxtファイルを除外（dir1は表示される）
```shell
[root@rocky86 0723]# find -path './dir1' -prune -o -name "*.txt"
./dir1
./test-a.txt
./test-b.txt
./dir4/f-x.txt
./dir4/f-y.txt
```
##### アクションが後の条件に適用される
```shell
[root@rocky86 0723]# find -path './dir1' -prune -o -name "*.txt" -print
./test-a.txt
./test-b.txt
./dir4/f-x.txt
./dir4/f-y.txt
```
##### 複数のディレクトリを除外
```shell
[root@rocky86 0723]# find \( -path './dir1' -o -path './dir4' \) -prune -o -name "*.txt" -print
./test-a.txt
./test-b.txt
```

### 1.2.9 ファイルサイズによる検索
`-size [+|-]N UNIT` # Nは数値、UNITは k, M, G, c(byte) などの単位
#### 解説
- `10k` # (9k, 10k]、9kより大きく10k以下
- `-10k` # [0k, 9k]、0k以上9k以下
- `+10k` # (10k, ∞)、10kより大きい

#### 例：
##### 4Kより大きく、5K以下のファイルを検索
```shell
[root@rocky86 0723]# find /var/log/ -size 5k -ls
2824532 8 -rw------- 1 root root 4842 Jul 23 09:27 /var/log/vmware-vmtoolsd-root.log
135920541 8 -rw-r--r-- 1 root root 4314 Jul 5 11:21 /var/log/httpd/access_log
```
##### 2k以下のファイルを検索
```shell
[root@rocky86 0723]# find /var/log/ -size -3k -name "*gz" -ls
70185831 4 -rw------- 1 root root 361 Jul 10 09:29 /var/log/sssd/sssd_kcm.log-20220710.gz
138549549 4 -rw-r----- 1 mysql mysql 639 Jul 20 16:10 /var/log/mysql/mysqld.log-20220721.gz
138733445 4 -rw-r----- 1 mysql mysql 218 Jul 21 22:12 /var/log/mysql/mysqld.log-20220722.gz
```
##### 2kより大きいファイルを検索
```shell
[root@rocky86 0723]# find /var/log/ -size +2k -name "*gz" -ls
68865518 12 -rw------- 1 root root 8611 Jul 9 14:26 /var/log/sssd/sssd_implicit_files.log-20220710.gz
68774184 28 -rw------- 1 root root 26635 Jul 9 17:37 /var/log/sssd/sssd_nss.log-20220710.gz
```
##### 2kより大きく、9k以下の
```shell
[root@rocky86 0723]# find /var/log/ -size +2k -size -10k -name "*gz" -ls
68865518 12 -rw------- 1 root root 8611 Jul 9 14:26
/var/log/sssd/sssd_implicit_files.log-20220710.gz
```
### 1.2.10 タイムスタンプによるファイル検索

ファイルのアクセス時間、変更時間、またはメタデータ変更時間に基づいてファイルを検索することができます。これは、日数または分数で指定することができます。

#### 時間の単位
- **日数で指定**
  - `-atime [+|-]N` # ファイルが最後にアクセスされた時間（日）
  - `-mtime [+|-]N` # ファイルの内容が最後に変更された時間（日）
  - `-ctime [+|-]N` # ファイルのメタデータが最後に変更された時間（日）

- **分で指定**
  - `-amin [+|-]N` # ファイルが最後にアクセスされた時間（分）
  - `-mmin [+|-]N` # ファイルの内容が最後に変更された時間（分）
  - `-cmin [+|-]N` # ファイルのメタデータが最後に変更された時間（分）

#### 解説
- `N` # [N, N+1)、N以上N+1未満、N日（分）目を意味します
- `+N` # [N+1, ∞]、N+1以上、つまりN+1日前（含む）を意味します
- `-N` # [0, N)、0以上N未満、N日（分）以内を意味します

#### 例：
##### 5分以内にアクセスされたファイルを検索
```shell
[root@rocky86 0724]# find -amin -5
```

##### 10分前にアクセスされたファイルを検索
```shell
[root@rocky86 0724]# find -amin +10
```

### 1.2.11 パーミッションによるファイル検索

`-perm [/|-]MODE` オプションを使用して、特定のパーミッションを持つファイルを検索します。

#### モード指定
- **MODE** # 精確なパーミッションマッチ
- **/MODE** # `u,g,o`のどれか一つのオブジェクトが指定したパーミッションビットを持っていればマッチ（OR関係）
- **-MODE** # `u,g,o`全てのオブジェクトが指定したパーミッションビットを持っていなければならない（AND関係）

#### 解説
- `0` # パーミッションビットが`0`の場合、そのロールのパーミッションは無視されます

#### 例：
##### 精確に `r` パーミッションのみを持つファイルを検索
```shell
[root@rocky86 0724]# find -perm 444 -ls
1835416 0 -r--r--r-- 1 root root 0 Jul 25 09:12 ./f-2.txt
```

##### `u,g,o` のいずれかが `r` パーミッションを持つファイルを検索（OR関係）
```shell
[root@rocky86 0724]# find -perm /444 -ls
1835414 0 drwxr-xr-x 2 root root 111 Jul 25 09:22 .
1835416 0 -r--r--r-- 1 root root 0 Jul 25 09:12 ./f-2.txt
1835419 0 -rw-r--r-- 1 root root 0 Jul 25 09:17 ./f-5.txt
1835420 0 -rwxrwxrwx 1 root root 0 Jul 25 09:17 ./f-6.txt
1835421 0 -r---w---x 1 root root 0 Jul 25 09:22 ./f-8.txt
```

##### `u,g,o` 全てが `r` パーミッションを持つ必要があるファイルを検索（AND関係）
```shell
[root@rocky86 0724]# find -perm -444 -ls
1835414 0 drwxr-xr-x 2 root root 111 Jul 25 09:22 .
1835416 0 -r--r--r-- 1 root root 0 Jul 25 09:12 ./f-2.txt
1835419 0 -rw-r--r-- 1 root root 0 Jul 25 09:17 ./f-5.txt
1835420 0 -rwxrwxrwx 1 root root 0 Jul 25 09:17 ./f-6.txt
```

##### 属主が `r` または `w` パーミッションを持つファイルを検索
```shell
[root@rocky86 0724]# find -perm /600 -ls
1835414 0 drwxr-xr-x 2 root root 111 Jul 25 09:22 .
1835416 0 -r--r--r-- 1 root root 0 Jul 25 09:12 ./f-2.txt
1835417 0 --w--w--w- 1 root root 0 Jul 25 09:12 ./f-3.txt
1835419 0 -rw-r--r-- 1 root root 0 Jul 25 09:17 ./f-5.txt
1835420 0 -rwxrwxrwx 1 root root 0 Jul 25 09:17 ./f-6.txt
1835421 0 -r---w---x 1 root root 0 Jul 25 09:22 ./f-8.txt
```

##### 属主が最低でも `rw` パーミッションを持つファイルを検索
```shell
[root@rocky86 0724]# find -perm -600 -ls
1835414 0 drwxr-xr-x 2 root root 111 Jul 25 09:22 .
1835419 0 -rw-r--r-- 1 root root 0 Jul 25 09:17 ./f-5.txt
1835420 0 -rwxrwxrwx 1 root root 0 Jul 25 09:17 ./f-6.txt
``` 

### 1.2.12 正規表現

ファイル名やパス名などのパターンを指定してファイルを検索する場合に、正規表現を使用することができます。

- `-regextype type` # 正規表現の種類を指定します。`emacs|posix-awk|posix-basic|posix-egrep|posix-extended`
- `-regex pattern` # 正規表現パターンを指定します。

#### 例:
```shell
[root@rocky86 0724]# find -regextype posix-egrep -regex ".*log"
./ls.log
[root@rocky86 0724]# find -regextype posix-egrep -regex ".*5.*"
./f-5.txt
```

### 1.2.13 処理アクション

ファイルが見つかった場合の処理アクションを指定できます。

- `-print` # デフォルトの処理アクションで、ファイルのパスを表示します。
- `-print0` # 改行せずに出力し、xargsと組み合わせて使用されます。
- `-ls` # `ls -ils`コマンドのフォーマットでファイルを表示します。
- `-fls file` # ファイルの長い形式の情報を指定したファイルに保存します。
- `-delete` # 見つかったファイルを削除します。慎重に使用してください！
- `-ok COMMAND {} \;` # 見つかった各ファイルにCOMMANDで指定したコマンドを実行します。各ファイルに対してコマンドを実行する前に、ユーザーに確認が求められます。
- `-exec COMMAND {} \;` # 見つかった各ファイルにCOMMANDで指定したコマンドを実行します。
- `{}` # 見つかったファイル名自体を参照するために使用します。

#### 例:
```shell
# デフォルトの -print
[root@rocky86 0724]# find
.
./f-1.txt
./f-2.txt
./f-3.txt

# 長い形式で表示
[root@rocky86 0724]# find -ls
1835414 0 drwxr-xr-x 2 root root 213 Jul 25 09:45 .
1835415 0 ---------- 1 root root 0 Jul 25 09:12 ./f-1.txt
1835416 0 -r--r--r-- 1 root root 0 Jul 25 09:12 ./f-2.txt
1835417 0 --w--w--w- 1 root root 0 Jul 25 09:12 ./f-3.txt

# 検索結果をファイルに保存
[root@rocky86 0724]# find -fls ls.log

# 削除
[root@rocky86 0724]# find -name "*.sh" -delete

# log で終わるファイルのバックアップ
[root@rocky86 0724]# find -name "*log" -exec cp {} {}.bak \;
[root@rocky86 0724]# ls *log*
f-1.log f-1.log.bak f-2.log f-2.log.bak f-3.log f-3.log.bak

# 15分以上アクセスされていないファイルを削除
[root@rocky86 0724]# find -amin +15 -ok rm {} \;
< rm ... ./f-1.txt > ?

# other のパーミッションに書き込み権限があるファイルから書き込み権限を削除
[root@rocky86 0724]# find -perm -002 -exec chmod o-w {} \;

# パーミッションが644で、拡張子がshの通常のファイルに実行権限を追加
[root@rocky86 0724]# find -type f -perm 644 -name "*.sh" -exec chmod 755 {} \;
```

## 1.3 パラメータ置換 xargs

多くのコマンドがパイプ`|`を用いてパラメータを渡すことができないため、より柔軟なパラメータを使用するには`xargs`を用いてコマンドのパラメータを生成する必要があります。`xargs`は標準入力からデータを読み込み、空白文字または改行文字でデータを分割し、それを別のコマンドのパラメータとして使います。さらに、多くのコマンドは多数のパラメータを受け入れることができず、コマンドの実行が失敗する可能性がありますが、`xargs`はこの問題も解決できます。

### 使用法

```shell
xargs [OPTION]... COMMAND [INITIAL-ARGS]...
```

### よく使用されるオプション

- `-0`、`--null` # ASCIIの0またはnullを区切り文字として使用
- `-a`、`--arg-file=FILE` # ファイルから入力を読み込む
- `-d`、`--delimiter=CHARACTER` # 区切り文字を指定
- `-E END` # 指定した終端文字に達した時点で停止
- `-L`、`--max-lines=N` # 標準入力からN行を一度に読み込んでcommandに渡す
- `-n`、`--max-args=MAX-ARGS` # 一度に使用するパラメータの最大数
- `-p`、`--interactive` # 実行前に確認
- `-r`、`--no-run-if-empty` # xargsの入力が空の場合は停止
- `-s`、`--max-chars=MAX-CHARS` # コマンドラインの最大文字数
- `-t`、`--verbose` # 実行過程を表示し、実行するコマンドを先に印刷
- `-x`、`--exit` # 主に-sと組み合わせて使用される

### 例

```shell
# パイプでパラメータを渡せない例
[root@rocky86 0724]# echo "f-1.log" | ls

# コマンド展開
[root@rocky86 0724]# ls `echo f-1.txt`
f-1.txt

# xargsを使用
[root@rocky86 0724]# echo "f-1.log" | xargs ls
f-1.log

# 標準入力をサポートしていないコマンドをサポートする
[root@rocky86 0724]# xargs ls -l
f-1.log
-rw-r--r-- 1 root root 0 Jul 25 09:43 f-1.log

# 標準入力からのリダイレクトをサポートするコマンド
[root@rocky86 0724]# cat ls.log
f-1.log
f-2.log
[root@rocky86 0724]# xargs -a ls.log ls -l
-rw-r--r-- 1 root root 0 Jul 25 09:43 f-1.log
-rw-r--r-- 1 root root 0 Jul 25 09:43 f-2.log

# 区切り文字を指定する
[root@rocky86 ~]# echo -e "1-2-3\c" | xargs -d '-'
1 2 3

# 2つのパラメータごとに実行
[root@rocky86 0724]# echo {1..5} | xargs -n 2
1
2
3
4
5

### 批量ユーザー作成とコマンド表示

```shell
[root@rocky86 0724]# echo user{1..5} | xargs -t -n1 useradd
useradd user1
useradd user2
useradd user3
useradd user4
useradd user5
```

### 批量ユーザー削除

```shell
[root@rocky86 0724]# echo user{1..5} | xargs -n1 userdel -r
```

### 批量ファイル作成例

```shell
[root@rocky86 0724]# df -i
Filesystem  Inodes   IUsed   IFree IUse% Mounted on
devtmpfs    220937   400     220537 1% /dev
/dev/mapper/rl-root 36700160 285100 36415060 1% /
/dev/mapper/rl-home 66568192 101    66568091 1% /home
/dev/sda1   524288   313     523975 1% /boot
# パラメータが長すぎて実行失敗
[root@rocky86 test]# touch f-{1..523975}.txt
-bash: /usr/bin/touch: Argument list too long
# 1万ファイルを一度に作成
[root@rocky86 test]# echo f-{1..523975}.txt | xargs -n 10000 touch
# inode リソースが枯渇
[root@rocky86 test]# df -i
Filesystem  Inodes   IUsed   IFree IUse% Mounted on
devtmpfs    220937   400     220537 1% /dev
/dev/mapper/rl-root 36700160 295396 36404764 1% /
/dev/mapper/rl-home 66568192 101    66568091 1% /home
/dev/sda1   524288   524288 0      100% /boot
```

### bilibili動画のバッチダウンロード

```shell
[root@rocky86 ~]# yum install python3-pip -y
[root@rocky86 ~]# pip3 install you-get
# インストールが失敗した場合のコマンド
[root@rocky86 ~]# pip3 --default-timeout=100 install -U you-get
# バッチダウンロード
[root@rocky86 ~]# seq 60 | xargs -i -P3 you-get https://www.bilibili.com/video/BV14K411W7UF?p={}
```

### ASCII空白文字によるパラメータ分割

```shell
[root@rocky86 0724]# ls
'a b' f-1.txt f-2.txt f-3.txt
[root@rocky86 0724]# find -type f | xargs echo
./f-1.txt ./f-2.txt ./f-3.txt ./a b
# デフォルトの空白文字によりファイル名が分割された例
[root@rocky86 0724]# find -type f | xargs ls
ls: cannot access './a': No such file or directory
ls: cannot access 'b': No such file or directory
./f-1.txt ./f-2.txt ./f-3.txt
# 正常に表示
[root@rocky86 0724]# find -type f -print0 | xargs -0 ls
'./a b' ./f-1.txt ./f-2.txt ./f-3.txt
```