Bashのプロンプトをカスタマイズする

BUW(Bash on Ubuntu on Windows)の標準シェルとなるBashは、ディレクトリ「/etc」やホームディレクトリに用意した定義ファイルで環境設定を行っている。BUWのホームディレクトリを確認すると、「~/.bash_history」「~/.bash_logout」「~/.bashrc」「~/.profile」といったファイルを確認できるはずだ。

「~/.bash_history」はBash上で実行したコマンドの履歴を格納し、「~/.bash_logout」は「exit」コマンドを実行するなどしてログアウトする際に実行する。ポイントは「~/.bashrc」「~/.profile」の2ファイル。そもそもBashは全ユーザーが参照および適用する「/etc/profile」と、ユーザー単位の設定を記述して適用する「~/.bash_profile」などを参照する仕組みだ。「~/.bashrc」はあくまでもBash起動時に読み込まれる設定ファイルだが、「~/.bash_profile」はBashが標準シェル設定時に最初だけ参照する設定ファイルである。

ログインシェルとインタラクティブ(対話型)シェルにおける定義ファイルの読み込み順番

つまりzshなど他のシェルを使う場合は「~/.profile」の設定が重要になるものの、あくまでも「Bashを使う」ということであれば、「~/.bashrc」もしくは「~/.bash_profile」に記述を追記していけば、Bashのカスタマイズが可能になるのだ。本稿では「~/.bashrc」の記述を推奨する。

あまりにもベタで恐縮だが、Bashのプロンプトをカスタマイズしてみよう。まずは「~/.bashrc」の末尾に「export PS1="[\t \u@\h \w \$] "」を追記してほしい。テキストエディターを終了させたら、「source ~/.bashrc」とファイルの内容を読み込めば、プロンプトの表示内容が変化したことを確認できるだろう。

テキストエディターで「~/.bashrc」を開いて「export PS1="[\t \u@\h \w \$] "」を追記する

「source ~/.bashrc」と入力して[Enter]キーを押せば、「~/.bashrc」を読み直してプロンプトの表記が変化する

プロンプトで指定できる特殊文字は、以下の文字が使用可能だ。表で示したようにすべての文字に対しては最初に「\(円記号もしくはバックスラッシュ)」を付けるが、このルールは次に説明する配色設定も同じだ。

プロンプトで使用できる主な特殊文字

それでは配色にチャレンジしてみよう。まずはBashのプロンプトに下図に示した囲みの内容をそのままコピー&ペーストしてほしい。

PS1='\[\e[1;36m\]\t\e[1;32m\]\u\e[00m\]@\e[1;31m\]\h\e[1;33m\]\w \$ \[\e[00m\]'

すると時刻は水色、ユーザー名は緑色、コンピューター名は赤色、カレントディレクトリとプロンプトは黄色になったはずだ。これらはANSIカラーコードをそのまま指定することで配色できる。「\[」でシーケンスを指定し、「\e[1;31m\]」と記述すれば明るい赤色を指定するといった具合だ。各配色に関しては表にまとめたので、そちらを参照してほしい。

プロンプトに配色を加えた状態

配色指定を図で分解した状態

配色で使用できる特殊文字一覧

case文を使用する

それでは今回のシェルスクリプトを紹介しよう。4回にわたって画像ファイルの数字連番でリネームするシェルスクリプトを書いてきたが、今回はシェルスクリプトの整理に着目した。いつもどおり下記に示したシェルスクリプトをBUW上で作成し、「chmod 755」などを実行して実行可能な状態にしてほしい。

 #!/bin/bash

 Cmdname="$0"
 Number=1
 MaxSize=1200

 message() {
    echo "Usage: ${Cmdname} Directory" 1>&2
    exit 1
 }

 if [ "$#" -ne 1 ]; then
    message
 elif [ -d $1 ]; then
    cd $1

    for OldFile in *; do
        case ${OldFile##*.} in
            jpg|JPG|png)
                Width=`identify -format "%w" $OldFile`
                NewFile=$(printf %03d.jpg $Number)
                if [ ${Width} -gt $MaxSize ]; then
                    convert -density 72 -quality 90 -resize 1200x $OldFile $NewFile
                else
                    convert -density 72 -quality 90 $OldFile $NewFile
                fi
                rm $OldFile
                echo "Convert and Rename $OldFile to $NewFile."
                Number=$((Number+1))
                ;;
            txt|TXT)    echo "Skip File: " $OldFile ;;
            *) ;;
        esac
    done

 else
    message
 fi

それでは今回追加したコードを解説する。7~10行目はシェルスクリプト実行時にディレクトリを指定しなかった際のメッセージを関数(ファンクション)化した。関数とは一連の処理をまとめたものだが、前回までは同じコードを2箇所で使っていたため、関数にすることでコードの簡素化を実現している。

次は17行目のfor文。これまでは拡張子を指定して指定ディレクトリの内容をあらかじめ取捨選択していたが、今回は「for OldFile in *; do」とすべてのファイル/ディレクトリを対象としている。この取捨選択は18行目のcase文で処理することにした。指定した変数(${OldFile##*.})とパターン(jpg|JPG|png)がマッチした場合に処理が行われ、すべてに合致しない場合(*)の処理を実行する仕組みだ。

${OldFile##*.}」は変数内から拡張子だけを取り除く表記のため、17行目のfor文で取得したファイルの拡張子によって、19行目で画像ファイルの拡張子、32行目で除外する拡張子に分類させている。中身の処理内容は前回までと変わらないが、これで当初の目的である「指定したディレクトリ内の画像を連番の名前に変更し、他の画像形式をJPEG形式に統一する」という目的は達成できた。

今回のスクリプト実行結果。19行目で指定した拡張子がすべて対象になる。また32行目で指定した拡張子は「Skip~」というメッセージのみ表示する仕組みだ

次回からはまた異なるシェルスクリプトなどを例にBUWの活用方法を紹介しよう。

阿久津良和(Cactus)