rcmdnk's blog

lsを読まずにプログラマを名乗るな!

lsコマンドはコマンドライン操作を覚える時に真っ先に覚えるコマンドだと思います。

簡単なコマンドなので改めてマニュアルを読むことはあまりないかと思いますが ちょっと気になって読んでみてコラム表示などについてあまり良く知らなかったので メモしておこうと思います。

lsにはGNU版、BSD版がありますが、確認した限りでは以下のことは共通です。

lsのターミナルへの通常表示

ターミナル上でlsコマンドを打つと、

$ ls
Applications Documents    Dropbox      Movies       Pictures     tmp
Desktop      Downloads    Library      Music        Public       usr

こんな感じで横にいくつか列(column)を作って最小行で表示できる様(multi-column表示)に 表示してくれます。

この時、ディレクトリやファイルはソートされた状態で表示されますが 表示順は左の列から始まり下に行き、次の列に移り…という順序になっています。

ソートの方法はシステム設定($LANG等の値)によります。 もしくは-t(時間ソート)、-r(逆反転)などのlsのオプションでソートの方法を指定することも出来ます。

ls -x

-xを使うと表示順がまず最初の行を埋め(右に行く方向で進む)、次の行へ、という順番になります。

$ ls -x
Applications Desktop      Documents    Downloads    Dropbox      Library      Movies       Music        Pictures     Public
tmp          usr

こんな感じに。この時、-x無しのときとは違い 最初の行から埋めていく形になるためか、最初の行で表示できるだけ表示します。

ファイルやパイプに繋いだ時の表示

ターミナルに表示する際には複数列の表示でコンパクトに表示してくれますが、 ファイルに書き出すときやパイプなどに繋いだ時は 各ファイル、ディレクトリ間がスペースではなく全て改行コードで埋められます。

$ ls | less
Applications
Desktop
Documents
Downloads
Dropbox
Library
Movies
Music
Pictures
Public
tmp
usr
lines 1-12/12 (END)

これによってスペース名が入っているファイル名などがある場合でも、 for文とかに渡す際にIFS$'\n'(改行)を指定することでちゃんと回す事ができます。

この様にターミナル表示(標準出力時)とファイル等への書き込み時に違う表示にする様なプログラムは結構あります。 lsの場合もこれ以外にもファイルなどへの書き込み時にはカラー表示等も省かれます。

lsのソースコード(C言語)を読んでないので実際の実装は知りませんが シェルスクリプトでも同じ様な事が出来て、 簡単な例は下にあります。

ファイルやパイプに繋いだ時も複数列表示にしたい時

-Cオプションを使います。

$ ls -C | less
Applications  Downloads Movies    Public
Desktop   Dropbox   Music   tmp
Documents Library   Pictures  usr
lines 1-3/3 (END)

この時、ファイルに書き出してみると分かりますが 各ファイルやディレクトリ間はタブで埋められています。

なので直接lessで見ると崩れてしまいますが、

$ ls -C | cat
Applications    Downloads       Movies          Public
Desktop         Dropbox         Music           tmp
Documents       Library         Pictures        usr

みたいな感じでcatで見ると(もしくは一度ファイルに吐き出してそれをcatすると) きれいに揃って見えます。

ただし最初のlsと比べて列の数が少ない(行が多い)ことに気付くと思います。

これは、表示する際にls$COLUMNSというターミナルの横幅の文字数を見ていて、 ターミナル表示だと実際に表示しているターミナルのもの(この時は134)、 ファイルやパイプに流す際にはデフォルト80を使って表示を調整しているためです。

$COLUMNSはターミナルの大きさによって自動的に設定される環境変数ですが これを変更してあげればlsの表示を替えられます。 ただ直接変更すると色々不具合があるので

$ COLUMNS=100 ls

みたいに実行時だけ変更する様にするべきです。

また、この様に設定するとファイルやパイプに繋いだときでもその$COLUMNSの値を使ってくれます。 なのでターミナル表示と同じにしたければ

$ COLUMNS=$COLUMNS ls -C | cat
Applications    Documents       Dropbox         Movies          Pictures        tmp
Desktop         Downloads       Library         Music           Public          usr

みたいにすればターミナルのコラム数を使って同じ表示を出せます。

ターミナル表示で各行1ファイル/ディレクトリ表示したい時

逆に通常のターミナル表示で各行一つずつ表示したい時は

$ COLUMNS=1 ls
Applications
Desktop
Documents
Downloads
Dropbox
Library
Movies
Music
Pictures
Public
tmp
usr

みたいな感じにCOLUMNSを1にしてあげれば一つの名前で一杯になるので全て違う行に表示する事が出来ます。

column

ちなみにこの様なlsのmulti-columnな表示ですが、 columnというコマンドを使うと同じ様に整形された表示に出来ます。

test.txt
1
2
3
4
5
6
7
8
9
10
11
12
Applications
Desktop
Documents
Downloads
Dropbox
Library
Movies
Music
Pictures
Public
tmp
usr

なファイルを用意して、

$ column test.txt
Applications    Documents       Dropbox         Movies          Pictures        tmp
Desktop         Downloads       Library         Music           Public          usr

とすればlsと同じ結果に。

$ cat test.txt  | column
Applications    Documents       Dropbox         Movies          Pictures        tmp
Desktop         Downloads       Library         Music           Public          usr

みたいな感じでパイプで受けてとる事もできます。

columnにはlsと同様、行を埋めていく-xオプションがあります。

また、横幅はls同様$COLUMNSの値で決まり、ファイルへの出力等の場合にはデフォルト80になりますが、 これを変更するには-c 50の様に-cを使う事が出来ます。 lsの時の様にその場だけでCOLUMNSの値を変更することでも出来ますがより簡単に書けます。

当然ですがcolumnの場合はlsと違い特別なオプションをつけなくてもファイルへの出力でもmulti-columnな表示になります。

Sponsored Links
Sponsored Links

« Nexus5のバッテリーを交換してもうしばらく使う 飛行機にモバイルバッテリーを持ち込む祭の注意点 »

}