この図は私がよく使うコマンドを表しており,ダントツでls
コマンドの利用頻度が多いのがわかります.lsコマンドはディレクトリやファイルの一覧を表示するコマンドであり,Linuxを触る際は必ず触ります.
今回はls -l
の表示内容についてRasPiを使って整理します.
はじめに
アクセス権を確認する際に複数のユーザが存在していると確認が捗るので,ここではpi2ユーザを新規作成します.
pi@raspi:~ $ sudo adduser pi2 Adding userpi2' ... Adding new group
pi2' (1001) … Adding new userpi2' (1001) with group
pi2' … Creating home directory/home/pi2' ... Copying files from
/etc/skel' … New password: Retype new password: passwd: password updated successfully Changing the user information for pi2 Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] y pi@raspi:~ $ id pi2 uid=1001(pi2) gid=1001(pi2) groups=1001(pi2) pi@raspi:~ $ sudo -u pi2 echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
ちなみにデフォルトから若干変更があるかと思いますが,piユーザは以下のような状態となっています.PATHの内容は同じですが,所属グループはたくさん設定されています.
pi@raspi:~ $ id pi uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),105(input),109(netdev),112(bluetooth),999(spi),998(i2c),997(gpio) pi@raspi:~ $ sudo -u pi echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
ls -l の表示内容
ls
コマンドはファイルに関する様々な情報を表示することが出来ます.何が表示されているのか順に説明していきます.
pi@raspi:~ $ ls -l /home/ total 8 drwxr-xr-x 7 pi pi 4096 Jul 15 13:00 pi drwxr-xr-x 2 pi2 pi2 4096 Jul 15 13:05 pi2
total
ディレクトリ内のファイルに割り当てられたブロック単位のサイズの合計を表しています.-sオプションを使うと各ファイルに割り当てられたブロック単位のサイズを表示することができます.後から説明しますが,ここで表示されているサイズ4はディレクトリ自身のサイズです.
-s, –size print the allocated size of each file, in blocks
man ls
pi@raspi:~ $ ls -ls /home/ total 8 4 drwxr-xr-x 8 pi pi 4096 Jul 15 13:00 pi 4 drwxr-xr-x 2 pi2 pi2 4096 Jul 15 13:05 pi2
① ファイルの種別
最初の1文字目でファイルの種別を表しています.代表的なものは以下の通りです.通常のファイル,ディレクトリ,シンボリックの3つくらいを知っていればはじめのうちは事欠きません.
表記 | 種別 |
---|---|
– | 通常のファイル |
b | ブロックデバイス(ブロックスペシャルファイル) |
c | キャラクタデバイス(キャラクタスペシャルファイル) |
d | ディレクトリ |
l | シンボリックリンク |
s | ソケットファイル |
hostsとos-releaseを例にコマンドの結果を見てみましょう.それぞれ通常のファイルとシンボリックリンクであることがわかります.
pi@raspi:~ $ ls -l /etc/hosts /etc/os-release -rw-r--r-- 1 root root 127 Jun 4 21:58 /etc/hosts lrwxrwxrwx 1 root root 21 May 11 05:59 /etc/os-release -> ../usr/lib/os-release
② アクセス権 ④ 所有者とグループ
②と④については一緒に説明していきます.
まずはアクセス権.左から3文字毎に所有者のアクセス権,グループのアクセス権,その他のアクセス権の順で表示されています.それぞれの記号の意味は以下の通りです.この他にもいくつか特殊な権限がありますが,一旦置いておきます.
アクセス権はchmod
コマンドで変更することが出来,3文字のアクセス権毎に3ビットと捉えて755や644といった数値(8進数)で表す場合があります.実際にはアクセス権は内部的に16ビットの整数で保持されています.
表記 | 権限 | 数値表記 |
---|---|---|
r | 読み取り権 | 4 |
w | 書き込み権 | 2 |
x | 実行権 | 1 |
– | 権限なし | 0 |
続いて所有者とグループ.左から所有者,所属グループを表しています.
piユーザでファイルを作成して,ip2ユーザから参照してみます.pi2ユーザはsample.txtの所有者ではなく,piグループにも所属していませんので,その他のアクセス権が適用されます.その他のアクセス権は読み取り権のみ設定されているため,pi2ユーザはcat
コマンドで参照は出来ますが,ファイルの内容は変更出来ません.
pi@raspi:~ $ echo hoge > /tmp/sample.txt pi@raspi:~ $ ls -l /tmp/sample.txt -rw-r--r-- 1 pi pi 5 Jul 15 13:20 /tmp/sample.txt pi@raspi:~ $ su pi2 pi2@raspi:~ $ cat /tmp/sample.txt hoge pi2@raspi:~ $ echo 'message from pi2' > /tmp/sample.txt bash: /tmp/sample.txt: Permission denied
ちなみに/tmpディレクトリは全てのユーザが読み書きできる権限となっていますが,その他のアクセス権部分にスティッキービット(t)という特殊な権限が設定されています.この権限が設定されていると,所有者もしくはrootユーザしかファイルを削除できなくなります.
pi2@raspi:~ $ ls -ld /tmp/
drwxrwxrwt 8 root root 4096 Jul 15 13:35 /tmp/
pi2@raspi:~ $ rm /tmp/sample.txt
rm: remove write-protected regular file '/tmp/sample.txt'? y
rm: cannot remove '/tmp/sample.txt': Operation not permitted
pi@raspi:~ $ sudo usermod -a -G pi pi2 pi@raspi:~ $ id pi2 uid=1001(pi2) gid=1001(pi2) groups=1001(pi2),1000(pi) pi@raspi:~ $ su pi2 pi2@raspi:~ $ rm /tmp/sample.txt rm: remove write-protected regular file '/tmp/sample.txt'? y rm: cannot remove '/tmp/sample.txt': Operation not permitted pi2@raspi:~ $ exit pi@raspi:~ $ sudo usermod -G pi2 pi2 pi@raspi:~ $ id pi2 uid=1001(pi2) gid=1001(pi2) groups=1001(pi2)
③ リンク数
対象が通常のファイルの場合,この数字はファイルのハードリンク数を表しています.
実際にファイルとそのハードリンクを作成してみます.Linux内部ではinodeを使ってファイルを管理していますが,同じinodeのファイルが2つありリンク数も2に増えていることがわかります.ここではシンボリックリンクも作成していますが,これはカウントされていません.
pi@raspi:~ $ echo 'num of links' > /tmp/sample.txt pi@raspi:~ $ ls -l /tmp/sample.txt -rw-r--r-- 1 pi pi 13 Jul 15 13:50 /tmp/sample.txt pi@raspi:~ $ ln /tmp/sample.txt /tmp/sample_hlink.txt # create hard link pi@raspi:~ $ ln -s /tmp/sample.txt /tmp/sample_slink.txt # create symbolic link pi@raspi:~ $ ls -li /tmp/sample* 2965 -rw-r--r-- 2 pi pi 13 Jul 15 13:51 /tmp/sample_hlink.txt 2845 lrwxrwxrwx 1 pi pi 15 Jul 15 13:51 /tmp/sample_slink.txt -> /tmp/sample.txt 2965 -rw-r--r-- 2 pi pi 13 Jul 15 13:50 /tmp/sample.txt
ディレクトリの場合はハードリンクを作成出来ず,上記とは考え方が異なります.実際にディレクトリを作成して確認してみます.
新しく作成したディレクトリはリンク数部分が2となっています.ディレクトリの中身を-aオプションをつけて確認してみると,自身と親ディレクトリへのリンクがあることがわかります.これがリンク数2の正体です.
pi2@raspi:~ $ mkdir test-a test-b pi2@raspi:~ $ ls -l total 8 drwxr-xr-x 2 pi2 pi2 4096 Jul 15 14:00 test-a drwxr-xr-x 2 pi2 pi2 4096 Jul 15 14:00 test-b pi2@raspi:~ $ ls -la test-a/ total 8 drwxr-xr-x 2 pi2 pi2 4096 Jul 15 14:00 . # itself drwxr-xr-x 4 pi2 pi2 4096 Jul 15 14:00 .. # parent directory
このディレクトリ内にファイルやディレクトリを配置してみます.ディレクトリ内にサブディレクトリを作成するとリンク数が増えましたが,ファイルを作成してもリンク数は変化ありません.つまりディレクトリにおけるリンク数とは,そのディレクトリに繋がるリンクの数を表しています.test-aディレクトリは,.(itself),..(parent),dir1,の3つに繋がっています.
pi2@raspi:~ $ mkdir test-a/dir1 pi2@raspi:~ $ ls -ld test-a/ drwxr-xr-x 3 pi2 pi2 4096 Jul 15 14:07 test-a pi2@raspi:~ $ touch test-a/sample.txt pi2@raspi:~ $ ls -ld test-a/ drwxr-xr-x 3 pi2 pi2 4096 Jul 15 14:08 test-a/ pi2@raspi:~ $ mkdir test-a/dir1/dir11 pi2@raspi:~ $ ls -ld test-a/ drwxr-xr-x 3 pi2 pi2 4096 Jul 15 14:08 test-a/ pi2@raspi:~ $ tree . ├── test-a │ ├── dir1 │ │ └── dir11 │ └── sample.txt └── test-b 4 directories, 1 file
ちなみにシンボリックリンクはカウントされません.
pi2@raspi:~ $ ln -s dir1 test-a/dir1_symbolic pi2@raspi:~ $ ls -ld test-a/ drwxr-xr-x 3 pi2 pi2 4096 Jul 15 14:15 test-a/ pi2@raspi:~ $ tree . ├── test-a │ ├── dir1 │ │ └── dir11 │ ├── dir1_symbolic -> dir1 │ └── sample.txt └── test-b 5 directories, 1 file
⑤ サイズ
対象がファイルの場合は,バイト単位のサイズを表しています.
適当な文字を書き込んだファイルsample.txtに対してls
コマンドでサイズを確認してみると11Byteとなっています.
pi@raspi:~ $ echo 'size check' > sample.txt
pi@raspi:~ $ ls -l sample.txt
-rw-r--r-- 1 pi pi 11 Jul 15 14:25 sample.txt
ちなみにファイルシステム上では4096Byte単位でサイズを割り当てるので,11Byteのファイルであってもduコマンドでは4.0Kとして表示されます.
pi@raspi:~ $ sudo tune2fs -l /dev/mmcblk0p2 | grep 'Block size' Block size: 4096 pi@raspi:~ $ du -h sample.txt 4.0K sample.txt
ディレクトリの場合も,ディレクトリ自身のサイズが表示されます.ここで注意したいのは,ディレクトリ自身のサイズというのはディレクトリの中身の合計サイズではありません.実際にディレクトリを作成して確認してみます.
作成したばかりのディレクトリのサイズが4096Byteとなっています.これがディレクトリ自身に割り当てられたサイズです.duコマンドの結果も4KByteとなっています.
pi@raspi:~ $ mkdir test pi@raspi:~ $ ls -ld test/ drwxr-xr-x 2 pi pi 4096 Jul 15 14:52 test/ pi@raspi:~ $ stat test/ File: test/ Size: 4096 Blocks: 8 IO Block: 4096 directory Device: b302h/45826d Inode: 134953 Links: 2 Access: (0755/drwxr-xr-x) Uid: ( 1000/ pi) Gid: ( 1000/ pi) Access: 2020-07-15 14:52:22.589490689 +0900 Modify: 2020-07-15 14:52:22.589490689 +0900 Change: 2020-07-15 14:52:22.589490689 +0900 Birth: - pi@raspi:~ $ du -h test/ 4.0K test/
ファイルシステムは4096Byte単位なので,ディレクトリ内にそれより少し大きいファイルを作成してしてみます.6MByteのファイルを作成してサイズを確認すると,du
コマンドの結果では6.1Mとサイズが大きくなっていますが,ls
コマンドの結果では4096Byteのまま変化していないことがわかります.
pi@raspi:~ $ dd if=/dev/zero of=test/file_6M bs=1M count=6 6+0 records in 6+0 records out 6291456 bytes (6.3 MB, 6.0 MiB) copied, 0.054627 s, 115 MB/s pi@raspi:~ $ ls -lh test/file_6M -rw-r--r-- 1 pi pi 6.0M Jul 15 14:55 test/file_6M pi@raspi:~ $ du -h test/ 6.1M test/ pi@raspi:~ $ ls -ld test/ drwxr-xr-x 2 pi pi 4096 Jul 15 14:55 test/ pi@raspi:~ $ stat test/ File: test/ Size: 4096 Blocks: 8 IO Block: 4096 directory Device: b302h/45826d Inode: 134953 Links: 2 Access: (0755/drwxr-xr-x) Uid: ( 1000/ pi) Gid: ( 1000/ pi) Access: 2020-07-15 14:52:22.589490689 +0900 Modify: 2020-07-15 14:55:32.813492930 +0900 Change: 2020-07-15 14:55:32.813492930 +0900 Birth: -
ちなみにstatコマンドで表示されているBlocksは8となっていますが,これは512Byte単位でカウントされています.どんどん話がそれてしまいそうなのでこのくらいにしておきます...
⑥ タイムスタンプ
タイムスタンプはいくつかの種類がありますが,ls -l
で表示されるものはmtimeです.これらのタイムスタンプはstat
コマンドでも確認出来ます.
タイムスタンプの種類 | 説明 | 確認コマンド |
---|---|---|
atime | accsess time ファイルまたはディレクトリのデータが最後にアクセスされた時刻 | ls -lu |
ctime | change time inodeのステータスが最後に変更された時刻 | ls -lc |
mtime | modify time ファイルまたはディレクトリのデータが最後に修正された時刻 | ls -l |
実際にファイルを作成して,これらのタイムスタンプがどのように更新されるのか確認します.
pi2@raspi:~ $ echo 'time stamp check' > sample.txt pi2@raspi:~ $ stat sample.txt File: sample.txt Size: 17 Blocks: 8 IO Block: 4096 regular file Device: b302h/45826d Inode: 133348 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1001/ pi2) Gid: ( 1001/ pi2) Access: 2020-07-15 15:56:09.056259375 +0900 Modify: 2020-07-15 15:56:09.056259375 +0900 Change: 2020-07-15 15:56:09.056259375 +0900 Birth: -
atimeは最後にアクセスした時刻を表します.OSやプログラムが動作する際には様々なファイルへアクセスを行いますが,その都度atimeを更新しているとパフォーマンスが低下します.したがってatimeの更新は,ファイルシステムのマウント時にnoatimeオプションで無効化するか,relatime(relative atime)オプションで更新頻度を下げたほうが良いです.relatimeは前回のatimeがmtimeまたはctimeより古い場合にatimeを更新します.
atimeを更新するのにcat
コマンドでファイルを参照する例がありますが,RasPiではルートファイルシステムにnoatimeオプションをつけてマウントしているためこの方法では変更出来ません.atimeオプションが付いていないファイルシステムで確認するか,touch
コマンドで直接atimeを更新してしまうことは出来ます.manではtouch
コマンドの-aオプションの説明は “change only the access time” となっていますが,inode内の属性値であるmtimeが更新されたのでctimeも更新されています.
pi2@raspi:~ $ mount | grep /dev/mmcblk0p2 /dev/mmcblk0p2 on / type ext4 (rw,noatime) pi2@raspi:~ $ touch -a sample.txt pi2@raspi:~ $ stat sample.txt File: sample.txt Size: 17 Blocks: 8 IO Block: 4096 regular file Device: b302h/45826d Inode: 133348 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 1001/ pi2) Gid: ( 1001/ pi2) Access: 2020-07-15 15:58:37.543468714 +0900 Modify: 2020-07-15 15:56:09.056259375 +0900 Change: 2020-07-15 15:58:37.543468714 +0900 Birth: -
mtimeはファイルやディレクトリを修正した際に更新されます.ファイルに文字列を追記してみるとmtimeが更新されていることがわかります.atimeと同様にここでもctimeが更新されています.
pi2@raspi:~ $ echo 'add message' >> sample.txt
pi2@raspi:~ $ stat sample.txt
File: sample.txt
Size: 29 Blocks: 8 IO Block: 4096 regular file
Device: b302h/45826d Inode: 133348 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1001/ pi2) Gid: ( 1001/ pi2)
Access: 2020-07-15 16:28:37.543468714 +0900
Modify: 2020-07-15 16:44:59.162220964 +0900
Change: 2020-07-15 16:44:59.162220964 +0900
Birth: -
⑦ ファイルやディレクトリの名前
これは説明するまでもなくファイルやディレクトリの名前です.
シンボリックリンクの場合はリンク先も表示されます.
おわりに
ls -l
の出力内容を整理しました.
全部知っていましたか?
コメント