f15: linux における 普通のファイル (regular file) とは？


/ 2023/07/02 訂正
/ ご指摘を受けまして、おっしゃりますとおり、
/ 普通(通常)のファイルの説明について
/ 考察が欠けておりましたので訂正いたします
/ 失礼いたしました

.
---

### **[ 1. 疑問 ]**

　bash のサンプルコードで、  
```bash:
　if [ -f test.txt ]; then
```
　というファイルチェックコードがあり、
　bash というか linux OS レベルにおいて

　-f オプションの意味を
　ネットで調べてみましたが、

　**・ファイルなら true**
　**・普通のファイルなら true**

　という答えがおおむねで、
　この、普通のファイル(通常のファイル) とは何ぞや
　という具体的な意味をいまさらですが、知りたくて
　ChatGPT 先生に聞いてみました

　※広義には unix になると思いますが、
　ディストリビューションによって違いはあるかもです

---
### **[ 2. 質問(1) ]**

　bash の if 文で、ファイル オプションに
　-f が使われている場合、
　普通のファイルなら true
　とありますが、普通のファイルとは、
　どういう意味ですか？

　-e の ファイルが存在するなら true
　との違いを教えてください

---
### **[ 3. 回答(1) ]**

　Bashの if 文で -f オプションが使われる場合、

　-f はファイルが存在し、かつ
　普通のファイル（通常のテキストファイルやバイナリファイル）
　である場合に条件を満たします

　つまり、 -f オプションはファイルの存在と同時に、
　それがディレクトリや特殊ファイル（デバイスファイルなど）
　ではないことを確認します

　一方、 -e オプションはファイルが存在する場合に条件を満たします
　これにはディレクトリや特殊ファイルも含まれます
　つまり、ファイルが存在するかどうかだけを確認し、
　ファイルの種類には関係しません

　例えば、以下のようなシェルスクリプトがあったとします：

```bash:
　#!/bin/bash

　filename="example.txt"

　if [ -f "$filename" ]; then
　  echo "The file exists and is a regular file."
　fi

　if [ -e "$filename" ]; then
　  echo "The file exists."
　fi
```

　もし example.txt が普通のテキストファイルであれば、
　上記のスクリプトは両方の条件を満たし、
　両方のメッセージを表示します
　しかし、もし example.txt がディレクトリだった場合、
　-f 条件は満たしませんが、 -e 条件は満たします

---
### **[ 4. 疑問のつづき ]**

　> 普通のファイルとは
　> 通常のテキストファイル や バイナリファイル で、
　> ディレクトリや特殊ファイル（デバイスファイルなど）ではない

　> -e オプションは
　> ディレクトリや特殊ファイルも含まれる
　> (-e はファイル専用ではないので、ディレクトリでも存在すれば true)

　という回答でした

　-f と -e でチェック内容が異なるので、違いがでるケースがある、
　ということで、-f と -e の違いの説明としては
　間違っていないと思います

　> 普通のファイルとは
　> 通常のテキストファイル や バイナリファイル で、

　ここの部分は断定せず、後述します

　続いて、同じようなことを思っている方の記事を見てみます

---
### **[ 5. regular file とは(1) ]**

　What is a Regular File ?
　https://www.javatpoint.com/what-is-a-regular-file

　(要約)

　普通(通常)のファイルとは、
　システムまたはユーザーが作成したデータを含む
　特定のファイル形式(レイアウト、プロパティ、ファイルフォーマット等)で
　生成されたファイルの一種

　cp、mv、rm、cat などの
　コマンドやユーティリティを使って操作することができる

　一般的には、ファイル拡張子で判断できるものであるが、
　ファイル拡張子がない場合もある

　普通(通常)ではないファイルとは
　ディレクトリ、特殊ファイル（デバイス・ファイル）、
　シンボリック・リンクなどがある

---
### **[ 6. regular file とは(2) ]**

　What is a regular file ?
　https://unix.stackexchange.com/questions/99276/what-is-a-regular-file

　(要約)

　・test コマンドで、通過できるものは、普通(通常)のファイル となる
　・stat コマンドでも、普通(通常)のファイル のチェックが可能

　・stat() 関数で、普通(通常)のファイルと
　　他のファイルタイプの違いについての識別がわかります
　　(st_mode という項目で以下の判断をすることが可能です)

　　S_IFMT     0170000   bit mask for the file type bit fields
　　S_IFSOCK   0140000   socket
　　S_IFLNK    0120000   symbolic link
　　-----------------------------------------
　　S_IFREG    0100000   regular file
　　-----------------------------------------
　　S_IFBLK    0060000   block device
　　S_IFDIR    0040000   directory
　　S_IFCHR    0020000   character device
　　S_IFIFO    0010000   FIFO
　　S_ISUID    0004000   set UID bit
　　S_ISGID    0002000   set-group-ID bit (see below)
　　S_ISVTX    0001000   sticky bit (see below)
　　S_IRWXU    00700     mask for file owner permissions
　　S_IRUSR    00400     owner has read permission
　　S_IWUSR    00200     owner has write permission
　　S_IXUSR    00100     owner has execute permission
　　S_IRWXG    00070     mask for group permissions
　　S_IRGRP    00040     group has read permission
　　S_IWGRP    00020     group has write permission
　　S_IXGRP    00010     group has execute permission
　　S_IRWXO    00007     mask for permissions for others (not in group)
　　S_IROTH    00004     others have read permission
　　S_IWOTH    00002     others have write permission
　　S_IXOTH    00001     others have execute permission


　statコマンドを試してみました
　(例：.deb / debian パッケージファイル)

```bash:
　$ stat google-chrome-stable_current_amd64.deb
　File: google-chrome-stable_current_amd64.deb
　Size: 82967408  Blocks: 162048  IO Block: 4096  regular file
　Device: 2h/2d   Inode: 168603511049686871  Links: 1
　Access: (0644/-rw-r--r--)  Uid: ( 1000/ usera)  Gid: ( 1000/ usera)
　Access: 2022-09-19 20:52:59.320756300 +0900
　Modify: 2022-03-29 21:53:06.000000000 +0900
　Change: 2022-09-19 20:51:55.812595900 +0900
　Birth: -
```
　Size: 行の最後に　regular file　と表示されてますね

　ちょっと角度を変えて「普通(通常)ではないファイル」
　について、質問してみました

---
### **[ 7. 質問(2) ]**

　linux OS においての
　「普通(通常)ではないファイル」とは
　どういったファイルのことですか？

---
### **[ 8. 回答(2) ]**

　「普通(通常)ではないファイル」とは、
　ディレクトリやシンボリックリンク、デバイスファイル、
　パイプ、ソケット、FIFOなど、通常のデータを格納するための
　ファイル（通常ファイル）以外の特殊なファイルのことを指します

　具体的なファイルの種類は以下のようになります:

　**- ディレクトリ（Directory）**: ファイルやサブディレクトリの
　　コンテナとして機能する特殊なファイル

　**- シンボリックリンク（Symbolic Link）**: 他のファイルや
　　ディレクトリへの参照を保持する特殊なファイル

　**- デバイスファイル（Device File）**: 
　　ハードウェアデバイスへのアクセスを提供する特殊なファイル
　　キャラクタデバイスやブロックデバイスなどが含む

　**- パイプ（Pipe）**: プロセス間の通信に使用される特殊なファイル

　**- ソケット（Socket）**: ネットワーク通信や
　　プロセス間通信（IPC）のための特殊なファイル

　**- FIFO（First In, First Out）**: プロセス間の通信に
　　使用される名前付きパイプ

---
### **[ 9. 普通(通常)ではないファイルの割り出し ]**

　「普通(通常)ではないファイル」について、おおむね間違いではなさそうですが、
　さらにファイルの種別について ls コマンドにて確認してみます

　ls コマンドでも、stat コマンド同様に、
　パーミッション情報の前の先頭の文字列で、ファイルの種別が確認できます

　**- : regular file
　d : directory
　c : character device file
　b : block device file
　s : local socket file
　p : named pipe
　l : symbolic link**

```bash:
　$ ls -ld google-chrome-stable_current_amd64.deb
　-rw-r--r-- 1 usera usera 82967408 Mar 29  2022 google-chrome-stable_current_amd64.deb

　-> regular file

　$ ls -ld /dev/null
　crw-rw-rw- 1 root root 1, 3 Jun 30 02:40 /dev/null

　-> character device file
```

　**・regular file**
　　通常ファイルは、Linuxシステムで最も一般的なファイル・タイプである
　　テキスト・ファイル、イメージ、バイナリ・ファイル、共有ライブラリ等

　　-> touch や echo コマンド (または vim, cat, リダイレクション) で作成

　**・directory**
　　Linuxにおいて、ディレクトリとは、
　　Windowsのような「入れ物」(フォルダ)単体を表す名称と言うよりも
　　ルートディレクトリ、カレントディレクトリといった、
　　「所在」や「階層」などの「位置」概念の意味合いを持つファイル・タイプ
　　(WindowsでもCドライブは階層的概念はあるが他のドライブは任意階層となる)

　　-> mkdir コマンドで作成

　**・character device file**
　**・block device file**

　　ユーザーやプログラムがハードウェア周辺機器と通信することを
　　可能にするファイルで、キャラクタデバイス
　　（またはキャラクタスペシャルファイル）は、
　　システムが一文字ずつデータを転送するバイトストリーム型機器
　　(キーボードやマウス，シリアル・インタフェースなど)を扱う

　　対して、ブロック・デバイスは、ブロック形式でデータを
　　やり取りする機器に対応し、
　　(主にハードドライブ/CD-ROMドライブ/メモリ領域等のハードウェアを管理する)
　　一般にバッファを使った入出力を行う

　　-> mknod コマンドで作成

　**・local socket file**
　　ソケットは、同一コンピュータ上のプロセス間ので通信
　　(IPC：Inter-Process Communication) を行うためのインタフェースの一種で、
　　ソケットファイルは、それらの通信を行うための拠点となる特殊なファイル

　　-> ソケットファイルは単体コマンドで作成するものではなく、
　　　　socketシステムコールを使用して ソケットが作成され、
　　　　bindシステムコールで、ソケットに名前をつけたら、
　　　　ファイルシステム上で ls で確認可能となる

　**・named pipe**
　　名前付きパイプは
　　無名パイプ(コマンド間の入出力を繋げるプロセス間通信の一種で、
　　使用しているプロセスが動作中のみ存在する)を拡張したもので、
　　名前付きパイプはファイルシステム上にファイルとして扱うことが可能

　　-> mkfifo コマンドで作成

　**・symbolic link**
　　シンボリックリンクは、元のファイルへのポインタとして
　　本体を参照できるように実体へのファイルパスだけを保持したファイル

　　-> ln -s コマンドで作成


　これらの stat や ls コマンドから「普通(通常)ではない」ファイルとは、
　以下の種類となり、

　**・bit mask for the file type bit fields
　・socket
　・symbolic link
　・block device (/dev/sda 等)
　・directory
　・character device (/dev/null, /dev/tty1, /dev/random 等)
　・FIFO (名前付きパイプ)
　・set UID bit
　・set-group-ID bit (see below)
　・sticky bit (see below)
　・mask for file owner permissions
　・owner has read permission
　・owner has write permission
　・owner has execute permission
　・mask for group permissions
　・group has read permission
　・group has write permission
　・group has execute permission
　・mask for permissions for others (not in group)
　・others have read permission
　・others have write permission
　・others have execute permission**

　それら以外が「普通(通常)のファイル」ということになります


### **[ 10. 普通(通常)のファイルとは ]**

　では「普通(通常)のファイル」についてみていきます

　これまで述べてきた中で「普通(通常)のファイル」とは、

　・テキストファイル、画像などのイメージファイル、バイナリファイル等
　・touch や echo コマンド で作成できるファイル
　・cp、mv、rm、cat などのコマンドを使って操作することができる

　ということになりますが、大前提となる ファイルシステム、および、
　ファイルシステムが管理する ファイル を踏まえて述べていきます


　**「ファイルシステム」**
　ハードディスクなどの記憶媒体の保存領域に
　ディレクトリの階層構造を用いてデータを記録(保存)・管理するための仕組み

　**「ファイル」**
　記録(保存)・管理される情報の単位(塊) を「ファイル」と呼ぶ


　**「普通(通常)のファイル」** (regular file) は、ファイルシステムにおいて
　特定のファイルタイプとして明示的に分類されない
　一般的なデータファイルを指します

　ファイルシステムでは、ファイルタイプに応じて異なる特性や
　操作方法が提供され、前述したディレクトリやシンボリックリンク等の
「普通(通常)ではない」ファイルは、特殊ファイルとして、
　それぞれ独自のファイルタイプとして識別され、
　特別な操作や動作が可能です

　一方「普通(通常)のファイル」は特定のファイルタイプとして
　明示的に指定されず、そのファイルの内容によって解釈されるものになります
　具体的には、通常のデータファイルとして扱われ、
　テキストファイルやバイナリファイル、画像ファイル、音声ファイルなど、
　さまざまな種類のデータを格納できます

　ファイルシステムはこれらのファイルの内容に対して
　特定の操作を提供しませんが、ユーザーアプリケーションやツールは
　ファイルの内容を解釈し、必要に応じて適切な処理を行います


　**「普通(通常)のファイル」の特徴**

　・データ(情報)を保存し、読み書きする
　　 (またはプログラム実行する) 機能を持ったもの
　・ファイルタイプの指定がなく、一般的なデータファイルとして扱われる
　・さまざまな形式のデータを格納できる
　・データの保持と操作に使用され、ファイル自体がデータを保持する
　・実行可能なコードを含むこともあり、
　　その場合はプログラムファイルとして実行される


　**「普通(通常)のファイル」である一般的な
　　データファイル、および、プログラムファイルの例**

　・テキストファイル: 文字や文字列を含む
　　テキストデータを格納するためのファイル形式
　　(.txt、.csv、.log など)

　・画像ファイル: 画像データを格納するためのファイル形式
　　(.jpg、.png、.gif、.bmp など)

　・音声ファイル: 音声データを格納するためのファイル形式
　　(.mp3、.wav、.aac など)

　・動画ファイル: 動画データを格納するためのファイル形式
　　(.mp4、.avi、.mov、.mkv など)

　・PDFファイル (.pdf): 
　　ポータブルドキュメントフォーマットで記述された
　　文書を格納するためのファイル形式

　・アーカイブファイル (.tar、.zip): 
　　複数のファイルやディレクトリをまとめて圧縮したり、
　　展開したりするためのファイル形式

　・データベースファイル (.db、.sqlite): 
　　データベースの情報を格納するためのファイル形式

　・実行可能ファイル: オペレーティングシステムや
　　プログラミング言語によって直接実行されるバイナリ形式
　　/bin/ の bash, netstat, mount, cat, rm, tee, ls, free などの
　　通常、シェルスクリプトやコマンドラインのインタープリタとして使用される
　　bash シェルの実行可能ファイルも、通常ファイルの扱いになってます

　・スクリプトファイル: インタープリタやランタイム環境によって
　　実行されるテキストベースのスクリプト
　　(.c、.sh、.py、.js など）


　**/bin/ 配下の実行可能ファイルの確認例**

```bash:
　$ ls -ld /bin/bash
　-rwxr-xr-x 1 root root 1183448 Jun 19  2020 bash
　$ ls -ld /bin/netstat
　-rwxr-xr-x 1 root root 158288 Feb  2  2019 netstat
　$ ls -ld /bin/mount
　-rwsr-xr-x 1 root root 55528 Feb  7  2022 mount
　$ ls -ld /bin/cat
　-rwxr-xr-x 1 root root 43416 Sep  5  2019 /bin/cat
　$ ls -ld /bin/rm
　-rwxr-xr-x 1 root root 72056 Sep  5  2019 rm
　$ ls -ld /bin/tee
　-rwxr-xr-x 1 root root 43384 Sep  5  2019 tee
　$ ls -ld /bin/ls
　-rwxr-xr-x 1 root root 142144 Sep  5  2019 ls
　$ ls -ld /bin/free
　-rwxr-xr-x 1 root root 26864 Sep  9  2021 free
```

---