以下を考慮してください。
me@mine:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
me@mine:~$ ./a.sh
Lines:
Columns:
me@mine:~$ echo "Lines: " $LINES
Lines: 52
me@mine:~$ echo "Columns: " $COLUMNS
Columns: 157
me@mine:~$
変数$LINES
および$COLUMNS
はシェル変数であり、not環境変数であるため、子プロセスにはエクスポートされません(ただし、xtermウィンドウのサイズを変更すると自動的に更新されます。リモートの場所からssh経由でログインした場合でも)。スクリプトに現在の端末サイズを知らせる方法はありますか?
編集:回避策としてこれが必要です この問題 :vi(vim、less、および同様のコマンドと同様)は、使用するたびに画面を台無しにします。端末を変更することはオプションではないため、回避策を探しています(スクロール$LINES
linesは確かに完璧なソリューションではありませんが、少なくとも前の画面を失うよりはましです)
tput
から行と列を取得できます。
#!/bin/bash
lines=$(tput lines)
columns=$(tput cols)
echo "Lines: " $lines
echo "Columns: " $columns
この質問は人気があるため、少しの追加情報を含む新しい回答を追加します。
多くの場合、最新のシステムでは、$COLUMNS
および$LINES
変数はnot環境変数です。シェルは各コマンドの後にこれらの値を動的に設定し、通常、非対話型スクリプトからこれらの値にアクセスすることはできません。一部のプログラムは、exportでこれらの値を尊重しますが、この動作は標準化されておらず、普遍的にサポートされていません。
Bashは、以下を使用してcheckwinsize
オプションを有効にすると、(環境ではなく)processプロセスのスコープでこれらの変数を設定します。
shopt -s checkwinsize
多くのシステムでは、デフォルトまたはシステム全体の起動ファイル(/ etc/bashrc または類似)、したがって、これらの変数が常に利用できるとは限らないことを覚えておく必要があります。 Cygwinなどの一部のシステムでは、このオプションはnot有効になっているため、上記の行を実行しない限り、Bashは$COLUMNS
および$LINES
を設定しませんそれを私たちに追加します 〜/ .bashrc。
非対話型スクリプトを作成する場合、通常、デフォルトでは$LINES
および$COLUMNS
に依存することは望ましくありません(ただし、canをチェックして、ユーザーが必要に応じて、端末サイズを手動でオーバーライドします)。
代わりに、stty
およびtput
ユーティリティは、スクリプトから端末サイズを決定するためのportable手段を提供します(説明されているコマンド以下は 現在POSIXの標準化が進行中 )です。
Puppe で受け入れられた回答に示されているように、tput
を使用して、非常に簡単な方法で端末サイズを収集できます。
lines=$(tput lines)
columns=$(tput cols)
または、size
のstty
クエリは、1行で端末の行と列の数を提供します(行数の後に2つのスペースとそれに続く列数として出力)。
size=$(stty size) # "40 80" for example
stty
プログラムには通常 GNU Coreutils が同梱されているため、tput
のないシステムでもよく見られます。私は時々stty
アプローチを好むが、これはコマンドとサブシェルを1つ少なくするため(Cygwinでは高価)であるが、出力を行と列に解析する必要があるため、読みにくい場合がある:
lines=${size% *}
columns=${size#* }
上記の両方のアプローチは、POSIXシェルで機能します。特にBashの場合、 process substitution を使用して、前の例を単純化できます。
read lines columns < <(stty size)
...これはtput
の例よりも高速ですが、少なくとも私のマシンでは最初のstty
の実装よりも低速です。実際には、パフォーマンスへの影響はおそらく無視できます。プログラムに最適なアプローチを選択してください(またはターゲットシステムで使用可能なコマンドに基づいて)。
何らかの理由でスクリプトで$LINES
と$COLUMNS
を使用したい場合は、これらの変数を環境にエクスポートするようにBashを構成できます。
trap 'export LINES COLUMNS' DEBUG
Bash DEBUG
トラップは、プロンプトで各コマンドが入力される前に実行されるため、これを使用してこれらの変数をエクスポートできます。各コマンドでそれらを再エクスポートすることにより、端末サイズが変更された場合に環境変数が最新のままであることを保証します。この行を追加します .bashrc 上記のcheckwinsize
オプションとともに。個人用スクリプトでは問題なく動作しますが、共有されるスクリプトでこれらの変数を使用することはお勧めしません。
eval $( resize )
その仕事をします...(xtermベースの端末上で)
kill -s WINCH $$
変数を設定します。
完了のために、「checkwinsize」オプションの設定はOPが探しているものとまったく同じですが、キャッチがあります。非対話型スクリプトではデフォルトでは設定されていませんが、スクリプトの先頭に次の行を追加して有効にすることができます。
shopt -s checkwinsize
残念ながら、LINESおよびCOLUMNS変数は、オプションを設定してもすぐには設定されません(少なくとも最後に試したとき)。代わりに、サブシェルが完了するまでBashを強制的に待機させる必要があり、その時点でこれらの変数が設定されます。したがって、この問題に対するBashのみの完全なソリューションは、次の行でスクリプトを開始することです。
shopt -s checkwinsize; (:;:)
その後、LINES変数とCOLUMNS変数を心ゆくまで使用できます。これらの変数は、外部ユーティリティを呼び出すことなく、端末のサイズが変更されるたびに正しい値にリセットされます。
ランニング help export
役立つかもしれません?
me@mine:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
me@mine:~$ ./a.sh
Lines:
Columns:
me@mine:~$ echo "Lines: " $LINES
Lines: 52
me@mine:~$ echo "Columns: " $COLUMNS
Columns: 157
me@mine:~$ export LINES COLUMNS
me@mine:~$ ./a.sh
Lines: 52
Columns: 157
me@mine:~$
あなたのシバンに言ってみましたか?
#!/bin/bash -i
bashの$LINES
および$COLUMNS
は、TTY ioctlの単なるシェルyラッパーであり、TTYのサイズと、サイズが変更されるたびに端末によって送信される信号を提供します。
これらのioctlを直接呼び出してTTYディメンションを取得する他の言語でプログラムを作成し、そのプログラムを使用できます。
編集:まあ、プログラムはすでに存在し、tput
と呼ばれます。投票する Puppeのtput
ベースの回答 。
#!/bin/bash -i
-i
は、現在、bash 4.2.10(1)-release on buntu 11.1で動作します。
$ cat show_dimensions.sh
#!/bin/bash -i
printf "COLUMNS = %d\n" $COLUMNS
printf "LINES = %d\n" $LINES
$ ./show_dimensions.sh
COLUMNS = 150
LINES = 101
$ bash --version
GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
数値はウィンドウのサイズを変更すると変わります。トラップは、スクリプトがSIGWINCHを取得していることを示しています。
次のようにexecコマンドで環境変数を使用しないのはなぜですか。
docker exec -ti -e LINES=$LINES -e COLUMNS=$COLUMNS container /bin/bash