Terminal penceresinin genişliğini ve yüksekliğini nasıl bulabilirim?


295

Basit bir örnek olarak, =terminal penceresinin tüm genişliği boyunca yazdırabilirsiniz bir CLI komut dosyası yazmak istiyorum .

#!/usr/bin/env php
<?php
echo str_repeat('=', ???);

veya

#!/usr/bin/env python
print '=' * ???

veya

#!/usr/bin/env bash
x=0
while [ $x -lt ??? ]; do echo -n '='; let x=$x+1 done; echo

Bu küçük node.js kütüphanesini sürekli olarak doğru pencere boyutu elde etmek için oluşturdum npmjs.com/package/window-size
jonschlinkert

Yanıtlar:


562
  • tput cols sütun sayısını gösterir.
  • tput lines satır sayısını söyler.

11
echo -e "lines\ncols"|tput -Shem çizgileri hem de sütunları almak için bkz: linux.about.com/library/cmd/blcmdl1_tput.htm
nickl-

4
tputterminalin durumunu okumak, imleci ve metin özelliklerini kontrol etmek vb. için birçok komut içeren harika bir komuttur .
Drew Noakes

2
Kullanışlı takma ad, örneğin: ile alias dim="echo $(tput cols)x$(tput lines)"sonuçlanabilir 80x50.
piskopos

2
Bu soru-cevap muhtemelen unix veya süper kullanıcı SE sitelerine aittir.
mydoghasworms

2
@bishop, sağladığınız takma ad komutu kabuk kaynaklandığında değerlendirilir. Diğer ad komutu için tek tırnak kullanmanız gerekir. Gibi: alias dim='echo Terminal Dimensions: $(tput cols) columns x $(tput lines) rows'
brandonsimpkins

103

Bash $LINESve $COLUMNSçevresel değişkenler hile yapabilmelidir. Terminal boyutunda herhangi bir değişiklik olduğunda otomatik olarak ayarlanır. (yani SIGWINCH sinyali)


18
Ancak, bu ortam değişkenleri yalnızca bash için kullanılabilir, bash içinde çalışan herhangi bir program için geçerli değildir (perl, python, ruby ​​gibi).
Br. Fatura

9
Bu, etkileşimli bash oturumundan başka bir şeyde çalışmaz (komut dosyasını çalıştırırsanız artık etkileşimli değildir). Bir komut dosyasında kullanabileceğiniz tek yer bash'deki istem_komuttur.
Doncho Gunchev

1
Aslında, checkwinsizeseçeneği ayarlarsanız etkileşimli olmayan komut dosyalarında çalışır . Örneğin, bu etkileşimli olmayan komut dosyası, üzerinde çalıştığı terminalin boyutlarını yazdırır: shopt -s checkwinsize; (:); echo $LINES $COLUMNS( checkwinsizeseçenek, yalnızca bir alt kabuğun bitmesini bekledikten sonra değişkenleri başlatır, bu nedenle (:)ifadeye ihtiyacımız vardır )
user3340662

$LINESve gönderildikten $COLUMNSsonra SIGWINCH, aslında herhangi bir etkileşimli komut yürütmesinden sonra güncellenir . Eğer güncelleme denerseniz PS1ile trap SIGWINCHkullanamazsınız sizin $LINESve $COLUMNSbunlar eski değerleri ((tutmak
gavenkoa

LINESve COLUMNSyalnızca bash tarafından kabuk değişkenleri olarak ayarlanır . Bu kabuk değişkenlerini dışa aktarmazsanız Bash bunları ortam değişkenleri olarak ayarlamaz .
Markus Kuhn

67

Ve orada sttygelen, coreutils

$ stty size
60 120 # <= sample output

Sırasıyla satır ve sütun sayısını veya yükseklik ve genişliği yazdıracaktır.

Sonra cutyaawk parçayı çıkarmak için tuşlarını .

Bu stty size | cut -d" " -f1yükseklik / çizgiler ve stty size | cut -d" " -f2genişlik / sütunlar içindir


Bu stil BORU ile çalışamaz, tput stilini kullanmanızı öneririz.
liuyang1

6
tput ile ilgili sorun, stty her tty'de mevcutken her zaman mevcut olmamasıdır. bu bilgi için teşekkürler!
iRaS

16
yes = | head -n$(($(tput lines) * $COLUMNS)) | tr -d '\n'

3
Soruya doğrudan bir cevap değil, harika bir demo senaryosu.
Chris Page

Ne güzel bir örnek!
Kurt Zhong

1
trtüm bu yıllar boyunca emri nasıl kaçırdım ? (facepalm)
Marco Massenzio

Bu hangi dil? Belirsiz sözdizimi hatalarına sahip bir kabuk komut dosyasına benziyor. (Kabukta, atamanın etrafında boşluklar işarete eşit olamaz ve ilk boru yerinde
görünmez

2
yes '='sonsuz miktarda '=' satır verir ve aşağıdaki komutlar terminali dolduracak kadar düzenlenir
pixelbeat

12

Bunu Windows CLI ortamında yapmak için, bulabilmemin en iyi yolu mode komutunu kullanmak ve çıktıyı ayrıştırmaktır.

function getTerminalSizeOnWindows() {
  $output = array();
  $size = array('width'=>0,'height'=>0);
  exec('mode',$output);
  foreach($output as $line) {
    $matches = array();
    $w = preg_match('/^\s*columns\:?\s*(\d+)\s*$/i',$line,$matches);
    if($w) {
      $size['width'] = intval($matches[1]);
    } else {
      $h = preg_match('/^\s*lines\:?\s*(\d+)\s*$/i',$line,$matches);
      if($h) {
        $size['height'] = intval($matches[1]);
      }
    }
    if($size['width'] AND $size['height']) {
      break;
    }
  }
  return $size;
}

Umarım faydalıdır!

NOT : Döndürülen yükseklik, arabellekteki satır sayısıdır, pencerede görünen satır sayısı değildir. Orada daha iyi seçenekler var mı?


3
Bununla ilgili bir soruna dikkat edin: Bu komutun çıktısı yerel ayara özgüdür. Başka bir deyişle, bu başka bir Windows yerel ayarında olduğu gibi çalışmaz. Windows 7'de aldığım şey bu: i.imgur.com/Wrr7sWY.png
Camilo Martin

Buna bir çözüm ekledi. +1 olsa!
Camilo Martin

10

TIOCGWINSZPOSIX'te , sonuçta (WINdow SiZe'yi Al) ioctl()çağrısını çağırmak istersiniz . Çoğu dilde bunun için bir çeşit sarıcı bulunmalıdır. Örneğin Perl'de Terim :: Boyut kullanabilirsiniz :

use Term::Size qw( chars );

my ( $columns, $rows ) = chars \*STDOUT;

1
Bunun için teşekkürler - beni doğru yöne yönlendirdi. İksir: :io.columnsErlang: io:columns(). erlang.org/doc/man/io.html#columns-0
Henrik N

2
TIOCGWINSZPOSIX standardında hiç yoktur ve ioctl()yalnızca eski STREAMS özelliği için tanımlanmıştır.
osvein

4

Lyceus cevapta belirtildiği gibi, kodu İngilizce olmayan yerel Windows üzerinde başarısız olacaktır, çünkü daha sonra çıktı mode"sütun" veya "satır" alt dizeleri içermeyebilir:

                                         mod komut çıkışı

Metin aramadan doğru alt dizeyi bulabilirsiniz:

 preg_match('/---+(\n[^|]+?){2}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];

Çizgilerle bile uğraşmadığımı unutmayın, çünkü güvenilmez (ve aslında onları umursamıyorum).

Düzenleme: Windows 8 hakkındaki yorumlara göre (oh ...), bunun daha güvenilir olabileceğini düşünüyorum:

 preg_match('/CON.*:(\n[^|]+?){3}(?<cols>\d+)/', `mode`, $matches);
 $cols = $matches['cols'];

Yine de test et, çünkü ben test etmedim.


Yönteminiz Win8'de çalışmıyor. Birden fazla ---satır alıyorum . i.imgur.com/4x02dqT.png
mpen

@ Mark İyi, harika, bu sadece güzel. Teşekkürler Windows. <3 (daha alakalı bir notta: Bunu nasıl düzelteceğimi göreceğim ... Windows 9 çıktığında: P).
Camilo Martin

Bu Bunu yapmak yoludur: $mode = `mode`; list($rows, $cols) = array_slice(preg_split('/\n/', substr($mode, strpos($mode, 'CON:'))), 2, 2);. Ve sonra sadece sayılar dışında her şeyi değiştiriyorum.
Aleksandr Makov

@AleksandrMakov Acaba sıralı diller varsa ne olur acaba CON device status:? Belki böyle bir şeyle eşleştirmek CON.*:daha iyi olur.
Camilo Martin

1
@ Mark Aslında kendimi tam olarak bu soruyu soruyordum. Bunu neden yaptım? Şüphe, ben sadece bir nedeni olduğunu varsayalım ve onunla gitti, lol.
Camilo Martin

1

@ Pixelbeat'ın cevabından esinlenerek, burada tputküçük bir printfdolgu / dolgu kullanımı vetr

printf "%0$(tput cols)d" 0|tr '0' '='

0

Satırlarınızın / LINES'lerinizin ve sütunlarınızın kullanılan "terminal" in gerçek boyutuyla eşleşmediği bazı durumlar vardır. Belki bir "tput" veya "stty" mevcut olmayabilir.

Boyutu görsel olarak kontrol etmek için kullanabileceğiniz bir bash işlevi. Bu, en fazla 140 sütun x 80 satıra kadar çalışır. Maksimum değerleri gerektiği gibi ayarlayabilirsiniz.

function term_size
{
    local i=0 digits='' tens_fmt='' tens_args=()
    for i in {80..8}
    do
        echo $i $(( i - 2 ))
    done
    echo "If columns below wrap, LINES is first number in highest line above,"
    echo "If truncated, LINES is second number."
    for i in {1..14}
    do
        digits="${digits}1234567890"
        tens_fmt="${tens_fmt}%10d"
        tens_args=("${tens_args[@]}" $i)
    done
    printf "$tens_fmt\n" "${tens_args[@]}"
    echo "$digits"
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.