Que vérifie [-t 1]?

Réponses:

14

[]est un raccourci de testcommande.

Selon man test:

-t FD
Vrai si FD est un descripteur de fichier associé à un terminal.

Donc, si vous exécutez bash en tant que shell interactif (terminal - voir ce fil pour l'explication de la terminologie), bash sera remplacé par zsh.

En savoir plus sur les fichiers .bash *:

Lorsque bash est appelé en tant que shell de connexion interactif ou en tant que shell non interactif avec l'option --login , il lit et exécute d'abord les commandes du fichier / etc / profile, si ce fichier existe. Après avoir lu ce fichier, il recherche ~ / .bash_profile, ~ / .bash_login et ~ / .profile, dans cet ordre, et lit et exécute les commandes à partir du premier qui existe et est lisible. L'option --noprofile peut être utilisée lorsque le shell est démarré pour inhiber ce comportement.

Lorsqu'un shell de connexion se ferme , bash lit et exécute les commandes des fichiers ~ / .bash_logout et /etc/bash.bash_logout, si les fichiers existent.

Lorsqu'un shell interactif qui n'est pas un shell de connexion est démarré, bash lit et exécute des commandes à partir de ~ / .bashrc , si ce fichier existe. Cela peut être inhibé en utilisant l'option --norc. L'option --rcfile file obligera bash à lire et exécuter des commandes à partir du fichier au lieu de ~ / .bashrc.

Commentaire de Stéphane Chazelas:
Notez qu'un shell peut être interactif sans que stdout soit un terminal, et un shell peut être non interactif avec un terminal sur stdout (comme à chaque fois que vous exécutez un script dans un terminal sans rediriger / canaliser sa sortie), et bashpeut lire .bashrcmême lorsqu'il n'est pas interactif (comme dans ssh host cmdoù se bashtrouve le shell de connexion de l'utilisateur sur l'hôte, ou bash --login -c 'some code'). case $- in *i*)...est la bonne façon de tester si un shell est interactif.

mrc02_kr
la source
4
Notez qu'un shell peut être interactif sans que stdout soit un terminal, et un shell peut être non interactif avec un terminal sur stdout (comme à chaque fois que vous exécutez un script dans un terminal sans rediriger / rediriger sa sortie), et bashpeut lire .bashrcmême lorsqu'il n'est pas interactif (comme ssh host cmdoù se bashtrouve le shell de connexion de l'utilisateur sur l'hôte, ou bash --login -c 'some code'où les .bash_profilesources le .bashrc). case $- in *i*)...est la bonne façon de tester si un shell est interactif.
Stéphane Chazelas
@ StéphaneChazelas bon point. Je contiendrai votre commentaire en réponse
mrc02_kr
Il existe différentes définitions de «interactif». Si le shell pense qu'il est interactif, alors iil sera défini (et dans les shells modernes qui peuvent être testés avec ifau lieu d'avoir à utiliser case). Mais il existe de nombreux cas d'utilisation où l'on ne se soucie que si stdout (ou stdin, ou stderr ...) est attaché à un terminal.
Mark Reed
9

La commande test [ -t 1 ] vérifie si la sortie de bash se trouve sur un terminal. L'intention de cette ligne est clairement d'exécuter zsh lors de l'ouverture d'un terminal, sans perturber les autres utilisations de bash. Mais c'est très mal fait.

Le fichier .bashrcest lu dans trois circonstances:

  • Lorsque bash est exécuté comme un shell interactif, c'est-à-dire pour exécuter des commandes tapées par l'utilisateur plutôt que pour exécuter des commandes batch.
  • Lorsque bash est un shell non interactif qui est exécuté par un démon RSH ou SSH (généralement parce que vous exécutez ssh host.example.com somecommandet bash est votre shell de connexion activé host.example.com).
  • Quand il est invoqué explicitement, par exemple dans un utilisateur .bash_profile( le choix de bash des fichiers de démarrage est un peu bizarre ).

[ -t 1 ]est un mauvais moyen de détecter les shells interactifs. Il est possible, mais rare, d'exécuter bash de manière interactive avec une sortie standard ne allant pas vers un terminal. Il est plus courant d'avoir une sortie standard vers un terminal dans un shell non interactif; un shell non interactif ne fonctionne pas, .bashrcmais malheureusement les shell bash invoqués par SSH le font. Il y a une bien meilleure façon: bash (et tout autre shell de style sh) fournit une méthode intégrée et fiable pour le faire.

case $- in
  *i*) echo this shell is interactive;;
  *) echo this shell is not interactive;;
esac

Donc, "lancez zsh s'il s'agit d'un shell interactif" devrait être écrit

case $- in
  *i*) exec zsh;;
esac

Mais même ce n'est pas une bonne idée: cela empêche d'ouvrir un shell bash, ce qui est utile même si vous utilisez zsh. Oubliez cet article de blog et configurez simplement votre raccourci qui ouvre un terminal pour exécuter zsh au lieu de bash. N'arrangez pas les choses pour que «chaque fois que vous ouvrez l'application Bash sur Windows, elle démarre maintenant avec le shell Zsh»: lorsque vous voulez zsh, ouvrez l'application Zsh.

Gilles 'SO- arrête d'être méchant'
la source
Pour rsh/ sshet pour le shell interactif, c'est si ce n'est pas un shell de connexion. Pour les shells de connexion ( sshdne démarre pas un shell de connexion non interactif, mais vous pouvez le faire avec ssh host exec bash -l), .bash_profileest lu à la place. Notez également que pour rsh/ ssh, vous devez également $SHLVLêtre non défini ou 0.
Stéphane Chazelas
5

test homme 1 :

-t FD

le descripteur de fichier FD est ouvert sur un terminal

Votre exemple s'exécute (remplace le processus en cours, dans ce cas bash) avec zshon si stdout est ouvert sur un terminal (pas un fichier / pipe / etc).

sebasth
la source