Table of Contents
記事の目的
任意のディレクトリに属するファイルやサブディレクトリを確認する際に使用するls
コマンドについて、
--color=auto
や--color=always
をoptionに指定すると、ファイルやディレクトリごとに色分けしてターミナルに出力してくれますが、
このauto
とalways
の挙動差はなんなのかを調べたいと思います.
ls --color=xxx
の仕組み
まず、マニュアルから確認します.
1
2
3
4
5
6
7
8
9
10
11
12
% man ls
DESCRIPTION
--color[=WHEN]
colorize the output; WHEN can be 'always' (default if omitted), 'auto', or
'never'; more info below
...
(略)
...
Using color to distinguish file types is disabled both by default and with --color=never.
With --color=auto, ls emits color codes only when standard output is connected to a ter‐
minal. The LS_COLORS environment variable can change the settings. Use the dircolors
command to set it.
このマニュアルを読む感じわかることは以下です:
- Ubuntu 20.04 LTSでは、デフォルトでは
--color
はdisabledされている --color
を指定するとデフォルトの挙動は--color=always
--color=auto
は標準出力先がTerminalの場合、カラー出力をしてくれるがそれ以外はしてくれない--color=always
は標準出力先がTerminal以外の場合でも、カラー出力をしてくれる
「標準出力先がTerminalの場合」とはなにを指しているのか?
Terminal上への出力:挙動差なし
このGithub Pagesブログのワークスペースディレクトリを例にまずコマンドの挙動を確認してみます:
このようにTerminal上でファイル要素を確認する場合は挙動差はありません.
パイプを用いて、出力結果を表示: 挙動差あり
リダイレクトを用いて、出力結果をテキストへWRITE:挙動差あり
次に、リダイレクトを用いて、ls
の出力結果をテキストへ吐き、そのテキストを確認してみます.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% ls --color=always -C > test.txt && nano test.txt
404.html feed.xml ^[[0m^[[01;34m_includes^[[0m/ offline.html README.md
about.html ^[[01;34mfonts^[[0m/ index.html package.json search.json
archive.html Gemfile ^[[01;34mjs^[[0m/ package-lock.json ^[[01;34m_site^[[0m/
_config.yml Gemfile.lock ^[[01;34m_layouts^[[0m/ ^[[01;34m_posts^[[0m/ sw.js
^[[01;34mcss^[[0m/ Gruntfile.js ^[[01;34mless^[[0m/ ^[[01;34mpwa^[[0m/ test.txt
^[[01;34m_doc^[[0m/ ^[[01;34mimg^[[0m/ LICENSE Rakefile
% ls --color=auto -C > test.txt && nano test.txt
404.html feed.xml _includes/ offline.html README.md
about.html fonts/ index.html package.json search.json
archive.html Gemfile js/ package-lock.json _site/
_config.yml Gemfile.lock _layouts/ _posts/ sw.js
css/ Gruntfile.js less/ pwa/ test.txt
_doc/ img/ LICENSE Rakefile
ls --color=always
の場合は、テキストへ出力された結果に文字列だけでなく、カラーコードも合わせて出力されていますls --color=auto
の場合は、文字列のみ
--color=always
を使用する場面の紹介
- Shellはzsh
- OSはDebian系(Ubuntu 20.04 LTS)
という前提条件のもと, 以下のような挙動をするls
を定義したいと思います
cd
コマンド実行時にファイル,ls
を同時に実行する- 出力結果は、ファイルやディレクトリの種類に応じて色分けされた形にしたい(
--color=always
や--color=auto
と同じ) - 出力行数が多いときは…で省略する
zshrcの設定例の紹介
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## ファイル数が多い時には省略表示
ls_abbrev() {
local cmd_ls='ls' # コマンドを格納するlocal変数を定義
local -a opt_ls # optionを格納するlocal変数の箱をarray型で定義
opt_ls=('-CF' '--color=always') # option local変数を代入
local ls_result
## CLICOLOR_FORCE=1でcolor出力を渡す
ls_result=$(CLICOLOR_FORCE=1 COLUMNS=$COLUMNS command $cmd_ls ${opt_ls[@]} | sed $'/^\e\[[0-9;]*m$/d')
local ls_lines=$(echo "$ls_result" | wc -l | tr -d ' ') #出力結果の行数をカウント
if [ $ls_lines -gt 10 ]; then #出力行数が11以上か未満で省略を切り分ける
echo "$ls_result" | head -n 5
echo '...'
echo "$ls_result" | tail -n 5
echo "$(command ls -1 -A | wc -l | tr -d ' ') files exist"
else
echo "$ls_result"
fi
}
autoload -Uz add-zsh-hook # hook関数の呼び出しをOKにする
add-zsh-hook chpwd ls_abbrev # chpwd(カレントディレクトリが変更したとき)をトリガーに ls_abbrevを実行する
挙動確認
1
2
3
% mkdir test && cd test
% touch foo_{01..40}.txt && mkdir hoo_{01..40}
% cd ./
現在の設定(2024.02.26追記)
現在は.zshrc
に以下のような alias設定 だけで済ませています
1
alias ls='ls -F --color=auto --group-directories-first'
なお, 一時的にフックしないでデフォルトのls
を実行したい場合は
1
% \ls
と入力することで一時的に alias を解除した実行が可能となります(=次のコマンドからはalias設定が再び有効になる).
恒久的にalias解除したい場合はunalias
コマンドを用いますが, 使う場面はあんまりありません.
References
- ls –color=auto, why they offer such an option since there is –color=always by default?
- シェルでコマンドの実行前後をフックする
(注意:GitHub Accountが必要となります)