Coreutils
UNIX系のOS(POSIX互換を意識したOS)には必ずと言ってよいほどlsコマンドやcatコマンドといったコマンドが含まれている。こうしたコマンドはLinuxに限らずUNIX系のOSには必須のコマンドだ。
Linuxディストリビューションでは、特にこうした基本となるコマンドを「GNU Core Utilities (Coreutils)」というパッケージから取ってきていることが多い。それ以外のUNIX系OSでは、OSごとにCoreutilsのようなコマンドを持っている。それらのコマンドは、パッケージというよりもOSの一部という位置付けになっている。
Linuxではディストリビューションが異なっていても、lsコマンドやrmコマンドといった基本的なコマンドの動作は同じことが多い。使っているコマンドがGNU Core Utilitiesに含まれているコマンドであり、基本的に同じだからだ。一方、それ以外のUNIX系OSでは、OSごとに基本となるコマンドの動作はちょっとずつ違っている。同じパッケージを使っているわけではなく、OSごとに独自のコマンドを実装しているからだ。
「POSIX」という“お約束ごと”があるため、こうしたコマンドの基本的な動作はどのUNIX系OSでも同じことが多い。しかし、POSIXで規定されていない動作に互換性はなく、提供されている追加機能もOSごとに異なる。こうした事実を知らないまま、Linuxのときと同じ要領でMacのコマンドを使おうとすると困ったことが出てくる。
Mac
Macはカーネル環境に*BSD系技術を取り込んでいるほか、ユーザーランドのコマンドをFreeBSDなどから移植して使っている。詳しい説明は省くが、要するにユーザーから見た場合、Macに最初からインストールされているコマンドは、Coreutilsのコマンドとはちょっと動きが違うのだ。
この辺りの基本的なコマンドはPOSIXで動作が定められており、定められている部分に関しては多くのUNIX系OSで互換性がある。しかし、それらの動作は基本的なものであり、便利な機能はそれぞれのOSやCoreutilsで拡張されていて、互換性がない。
また、動作としては同じでも出力されるフォーマットが微妙に異なるとか、表示されるデータに違いがあるといったこともある。こうした挙動の違いを知らずに同じコマンドだと思って使っていくと思わぬところでハマることがある。最初からこうしたコマンドには「共通する部分」と「互換性のない部分」の2種類があることを知っておこう。
以下に、Coreutilsに含まれているコマンドから、Macのコマンドと動作が違う部分をいくつか取り上げて紹介する。
date
日付を出力したり設定したりするdateコマンドはよく使われるコマンドの一つだが、日付を進めたり、戻したりするオプションには互換性がない。例えば、Mac dateコマンドでは-vオプションで日時を進めたり戻したりすることができる。例えば、1週間前の日時を出力する場合は次のようになる。
Mac date
% date -v-1w
Tue Dec 7 10:25:47 JST 2021
%
このコマンドはCoreutilsのdateコマンドには存在しておらず、同じようなことをする場合には次のように--dateオプションを使うことになる。
Coreutils date
% date --date '1 week ago'
Tue Dec 7 10:25:58 JST 2021
%
これらのオプションは拡張機能に分類されるものだが、便利なのでときどき使うのだ。しかし、OSごとに使い方が違うし、場合によってはこの機能は提供されていない。
df
dfコマンドはストレージの状態を出力するためのコマンドだが、OSごとに挙動が異なるコマンドでもある。大体の出力は似ているのだが、「Mac df」と「Linux df」では同じプラットフォームで実行しても次のように出力が異なっている。
Mac df
% df
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk3s1s1 1942700360 30653304 1714903320 2% 575614 4293053646 0% /
devfs 403 403 0 100% 699 0 100% /dev
/dev/disk3s6 1942700360 40 1714903320 1% 0 8574516600 0% /System/Volumes/VM
/dev/disk3s2 1942700360 932056 1714903320 1% 1452 8574516600 0% /System/Volumes/Preboot
/dev/disk3s4 1942700360 9512 1714903320 1% 52 8574516600 0% /System/Volumes/Update
/dev/disk1s2 1024000 12328 986424 2% 3 4932120 0% /System/Volumes/xarts
/dev/disk1s1 1024000 14568 986424 2% 30 4932120 0% /System/Volumes/iSCPreboot
/dev/disk1s3 1024000 960 986424 1% 33 4932120 0% /System/Volumes/Hardware
/dev/disk3s5 1942700360 194165984 1714903320 11% 628693 8574516600 0% /System/Volumes/Data
map auto_home 0 0 0 100% 0 0 100% /System/Volumes/Data/home
%
Coreutils df
% df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/disk3s1s1 971350180 113898520 857451660 12% /
/dev/disk3s6 971350180 113898520 857451660 12% /System/Volumes/VM
/dev/disk3s2 971350180 113898520 857451660 12% /System/Volumes/Preboot
/dev/disk3s4 971350180 113898520 857451660 12% /System/Volumes/Update
/dev/disk1s2 512000 18788 493212 4% /System/Volumes/xarts
/dev/disk1s1 512000 18788 493212 4% /System/Volumes/iSCPreboot
/dev/disk1s3 512000 18788 493212 4% /System/Volumes/Hardware
%
カーネルやサブシステムに機能が強く依存するタイプのコマンドは、OSごとに挙動が異なる傾向が強い。dfはそうしたコマンドの一つだ。
ls
Linuxを使っていく上で絶対に外すことのできないコマンドがlsコマンドだ。しかし、このコマンドもOSの癖や拡張機能などによって挙動が異なりやすい。Macで「Mac ls」と「Coreutils ls」を実行すると、次のような違いが出る。
Mac ls
% ls -l
total 48
-rw-r--r-- 1 daichi staff 1346 Oct 3 14:39 LICENSE
-rw-r--r-- 1 daichi staff 238 Oct 3 14:39 Makefile
drwxr-xr-x 6 daichi staff 192 Oct 3 14:39 data
-rw-r--r-- 1 daichi staff 432 Oct 3 14:39 main.c
-rw-r--r-- 1 daichi staff 74 Oct 3 14:39 main.h
-rw-r--r-- 1 daichi staff 2186 Oct 3 14:39 util_csv.c
-rw-r--r-- 1 daichi staff 449 Oct 3 14:39 util_file.c
%
Coreutils ls
% ls -l
total 24
-rw-r--r-- 1 daichi staff 1346 Oct 3 14:39 LICENSE
-rw-r--r-- 1 daichi staff 238 Oct 3 14:39 Makefile
drwxr-xr-x 6 daichi staff 192 Oct 3 14:39 data
-rw-r--r-- 1 daichi staff 432 Oct 3 14:39 main.c
-rw-r--r-- 1 daichi staff 74 Oct 3 14:39 main.h
-rw-r--r-- 1 daichi staff 2186 Oct 3 14:39 util_csv.c
-rw-r--r-- 1 daichi staff 449 Oct 3 14:39 util_file.c
%
「total」の出力や、出力フォーマットが多少異なっている。lsコマンドの出力結果を文字数ベースで切り取って操作するようなスクリプトを作って使っていたりすると、想定しているようには動いてくれなくなるわけだ。
stat
ファイルやディレクトリの詳細情報を得たい場合には、lsコマンドではなくstatコマンドを使った方が良いのだが、このコマンドも挙動がOSごとに異なりがちだ。MacとCoreutilsでは、それぞれ次のような挙動を見せる。
Mac stat
% stat .
16777234 7814491 drwxr-xr-x 11 daichi staff 0 352 "Oct 3 14:39:21 2021" "Oct 3 14:39:15 2021" "Oct 3 14:39:15 2021" "Oct 3 14:39:12 2021" 4096 0 0 .
%
Coreutils stat
% stat .
File: .
Size: 352 Blocks: 0 IO Block: 4096 directory
Device: 1,18 Inode: 7814491 Links: 11
Access: (0755/drwxr-xr-x) Uid: ( 501/ daichi) Gid: ( 20/ staff)
Access: 2021-10-03 14:39:21.280866865 +0900
Modify: 2021-10-03 14:39:15.684198006 +0900
Change: 2021-10-03 14:39:15.684198006 +0900
Birth: 2021-10-03 14:39:12.283140329 +0900
%
ファイルやディレクトリの情報、例えば作成日時や更新時刻などに基づいて処理を行うスクリプトを書きたいときがある。そんなときに便利なのがstatコマンドなのだが、このように動作がOSごとに異なる。Linux以外のOSでstatコマンドを使う場合には、そのOSのstatコマンドをよく調べて使う必要がある。
stty
ターミナルインタフェースとやりとりするためのsttyコマンドの動きも、OSごとに異なる傾向がある。次のような感じだ。
Mac stty
% stty
speed 9600 baud;
lflags: echoe echoke echoctl pendin
oflags: -oxtabs
cflags: cs8 -parenb
%
Coreutils stty
% stty
speed 9600 baud;
ixany
-echok
%
インタラクティブシェルやCUIエディタにおける入力、特にショートカットキー入力を調整するためのsttyコマンドを使うことがあるが、このコマンドもOSごとに動作が異なる傾向が見られる。
uname
システムの情報を出力させる最も基本的なコマンドの一つであるunameコマンドも、OSごとに挙動が変わりやすい。
Mac uname
% uname -a
Darwin Mac-mini-M1-2020.local 21.1.0 Darwin Kernel Version 21.1.0: Wed Oct 13 17:33:24 PDT 2021; root:xnu-8019.41.5~1/RELEASE_ARM64_T8101 arm64
%
Coreutils uname
% uname -a
Darwin Mac-mini-M1-2020.local 21.1.0 Darwin Kernel Version 21.1.0: Wed Oct 13 17:33:24 PDT 2021; root:xnu-8019.41.5~1/RELEASE_ARM64_T8101 arm64 arm64 Macmini9,1 Darwin
%
unameはシェルスクリプトを作成する際に、プラットフォームごとに動作を切り分ける場合などの起点処理として使われることの多いコマンドなのだが、オプションなど使い方を誤るとLinux以外では適切に動作しないスクリプトが出来上がったりする。
uptime
システムの稼働時間を表示するuptimeコマンドは、MacもCoreutilsも基本的には同じ動作をするが、次のように出力のフォーマットが多少異なっている。
Mac uptime
% uptime
10:38 up 4 days, 15:13, 3 users, load averages: 2.01 1.84 1.75
%
Coreutils uptime
% uptime
10:38:15 up 4 days 15:12, 3 users, load average: 2.01, 1.84, 1.75
%
文字数ベースでuptimeコマンドの出力を切り取って使うようなスクリプトを書いていると、こういった違いで処理が通らなくなる。
MacでCoreutilsを使うには
LinuxにCoreutilsをインストールできるように(そしてこれはデフォルトでインストールされていることがほとんどだ)、MacでもCoreutilsを使用することができる。Coreutilsを使いたければ、MacのコマンドではなくCoreutilsをインストールして使えばよい。
Coreutilsは前回取り上げたHomebrewを使ってインストールする。次のようにbrewコマンドを実行すればよい。
HomebrewでCoreutilsをインストール
brew install coreutils
Homebrew経由でインストールされたCoretutils系コマンドには「g」から始まる名前が付けられている。例えば、Coreutilsのlsコマンドは「gls」という名前で使えるようになっているし、catコマンドは「gcat」、rmコマンドは「grm」といった具合だ。
Coreutilsのコマンドの場合、コマンド名の先頭に「g」を付けるというのは、Macに限らずほかのUNIX系OSでもしばしば行われている方法なので覚えておくと良いかもしれない。普段使っているOSがLinuxであり、Macは時々使う程度、という場合には、こんな感じでCoreutilsをインストールしてそちらのコマンドを使うようにしてしまえば、“ズレ”を感じる瞬間を減らすことができるだろう。