Considérer ce qui suit:
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:~$
Les variables $LINES
et $COLUMNS
sont des variables shell et non des variables d’environnement et ne sont donc pas exscopes vers le processus enfant (mais elles sont automatiquement mises à jour lorsque je redimensionne la fenêtre xterm, même si vous êtes connecté via ssh à partir d’un emplacement distant). Y a-t-il un moyen de laisser mon script connaître la taille actuelle du terminal?
EDIT: J’ai besoin de ceci comme solution de contournement pour résoudre ce problème : vi (ainsi que vim, less et des commandes similaires) gâche l’écran à chaque fois que je l’utilise. Changer le terminal n’est pas une option, et donc je cherche des solutions de contournement (faire défiler les lignes $LINES
n’est certainement pas la solution parfaite, mais au moins c’est mieux que de perdre l’écran précédent)
Vous pouvez obtenir les lignes et les colonnes à partir de tput
:
#!/bin/bash lines=$(tput lines) columns=$(tput cols) echo "Lines: " $lines echo "Columns: " $columns
Parce que cette question est populaire, je veux append une nouvelle réponse avec un peu d’informations supplémentaires.
Souvent, sur les systèmes modernes, les variables $COLUMNS
et $LINES
ne sont pas des variables d’environnement. Le shell définit ces valeurs dynamicment après chaque commande et nous ne pouvons généralement pas y accéder à partir de scripts non interactifs. Certains programmes respectent ces valeurs si nous les exportons , mais ce comportement n’est pas standardisé ou pris en charge universellement.
Bash définit ces variables dans la scope du processus (pas l’environnement) lorsque nous checkwinsize
option checkwinsize
utilisant:
shopt -s checkwinsize
De nombreux systèmes activent cette option pour nous dans un fichier de démarrage par défaut ou à l’échelle du système ( / etc / bashrc ou similaire). Nous devons donc nous souvenir que ces variables ne sont pas toujours disponibles. Sur certains systèmes, tels que Cygwin, cette option n’est pas activée pour nous, donc Bash ne définit pas $COLUMNS
et $LINES
moins d’exécuter la ligne ci-dessus ou de l’append à notre ~ / .bashrc .
Lors de l’écriture de scripts non interactifs, nous ne souhaitons généralement pas utiliser par défaut $LINES
et $COLUMNS
(mais nous pouvons les vérifier pour permettre à un utilisateur de remplacer manuellement la taille du terminal si vous le souhaitez).
Au lieu de cela, les utilitaires stty
et tput
fournissent des moyens portables pour déterminer la taille du terminal à partir d’un script (les commandes décrites ci-dessous sont en cours de normalisation pour POSIX ).
Comme indiqué dans la réponse acceptée par Puppe , nous pouvons utiliser tput
pour collecter la taille du terminal de manière assez simple:
lines=$(tput lines) columns=$(tput columns)
Alternativement, la requête de size
pour stty
nous donne le nombre de lignes et de colonnes du terminal en une seule étape (sortie en nombre de lignes suivi de deux espaces suivis du nombre de colonnes):
size=$(stty size) # "40 80" for example
Le programme stty
est généralement livré avec GNU Coreutils , nous pouvons donc souvent le trouver sur des systèmes sans tput
. Je préfère parfois l’approche stty
car nous invoquons une commande et un sous-shell moins nombreux (coûteux sur Cygwin), mais cela nécessite que nous analysions la sortie en lignes et en colonnes, ce qui peut être moins lisible:
lines=${size% *} columns=${size#* }
Les deux approches décrites ci-dessus fonctionnent dans n’importe quel shell POSIX. Pour Bash en particulier, nous pouvons utiliser la substitution de processus pour simplifier l’exemple précédent:
read lines columns < <(stty size)
... qui est plus rapide que l'exemple de base, mais toujours plus lent que la première implémentation stty
, du moins sur ma machine. En pratique, l'impact sur les performances est probablement négligeable: choisissez l'approche qui convient le mieux au programme (ou en fonction de la commande disponible sur le système cible).
Si, pour une raison quelconque, nous voulons toujours utiliser $LINES
et $COLUMNS
dans nos scripts, nous pouvons configurer Bash pour exporter ces variables dans l'environnement:
trap 'export LINES COLUMNS' DEBUG
Le piège Bash DEBUG
s'exécute avant chaque saisie de la commande à l'invite, de sorte que nous pouvons l'utiliser pour exporter ces variables. En les réexportant avec chaque commande, nous nous assurons que les variables d'environnement restnt à jour si la taille du terminal change. Ajoutez cette ligne à .bashrc avec l'option checkwinsize
ci-dessus. Cela fonctionne bien pour les scripts personnels, mais je ne recommande pas d'utiliser ces variables dans un script qui sera partagé.
eval $( resize )
ce travail … (sur un terminal basé sur xterm)
kill -s WINCH $$
définit les variables.
Avez-vous essayé de faire votre shebang dire:
#!/bin/bash -i
Exécuter l’ help export
pourrait aider?
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:~$
$LINES
et $COLUMNS
dans bash est juste un wrapper de type shell-y autour des ioctls du TTY, vous donnant la taille du TTY et les signaux envoyés par le terminal chaque fois que cette taille change.
Vous pouvez écrire un programme dans une autre langue qui appelle directement ces ioctls pour accéder aux dimensions TTY, puis utiliser ce programme.
EDIT: Eh bien, il s’avère que ce programme existe déjà, et s’appelle tput
. Votez la tput
basée sur le tput
de Puppe .
Par souci d’achèvement, permettez-moi de mentionner que la définition de l’option ‘checkwinsize’ correspond exactement à ce que recherche l’OP, mais il y a un problème. Par défaut, il n’est pas défini dans les scripts non interactifs, mais vous pouvez choisir d’append la ligne suivante au début de tout script pour l’activer:
shopt -s checkwinsize
Malheureusement, les variables LINES et COLUMNS ne sont pas définies immédiatement lors de la définition de l’option (au moins la dernière fois que j’ai essayé). Au lieu de cela, vous devez forcer Bash à attendre qu’un sous-shell se termine, à quel point il définira ces variables. La solution complète de Bash uniquement à ce problème consiste donc à démarrer votre script avec la ligne suivante:
shopt -s checkwinsize; (:;:)
Vous pouvez ensuite utiliser les variables LINES et COLUMNS au contenu de votre cœur, et elles seront réinitialisées aux valeurs correctes chaque fois que le terminal est redimensionné, sans avoir à appeler aucun utilitaire externe.
#!/bin/bash -i
-i
fonctionne maintenant avec la version 4.2.10 (1) de bash sur Ubuntu 11.10 .
$ 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 This is free software; you are free to change and redissortingbute it. There is NO WARRANTY, to the extent permitted by law.
Les nombres changent avec un redimensionnement de fenêtre; un piège révèle que le script reçoit un SIGWINCH.
Pourquoi ne pas utiliser les variables d’environnement sur la commande exec comme ceci:
docker exec -ti -e LINES=$LINES -e COLUMNS=$COLUMNS container /bin/bash
Mon expérience est que vous devriez commencer le script par le ‘. script_to_run ‘form, au lieu de’ scritp_to_run ‘. Une simple vérification comme suit:
'(( ${#COLUMNS} )) || { echo "Try start like '. name'" ; return 1 ; }