@heemayl Merci. Pouvez-vous extraire les différences sur mon cas? Merci.
Nam G VU
1
Astuce: Les commandes de chaque côté de l' |exécution en sous-coquilles.
heemayl
Réponses:
21
Dans p=$(cd ~ && pwd):
La substitution de commande $(), s'exécute en sous-shell
cd ~change le répertoire en ~(votre home), si cdréussit ( &&) puis pwdimprime le nom du répertoire sur STDOUT, donc la chaîne sauvegardée psera votre répertoire home par exemple/home/foobar
Dans p=$(cd ~ | pwd):
$()Génère à nouveau un sous-shell
Les commandes des deux côtés de la |course dans les sous-coquilles respectives (et les deux démarrent en même temps)
ainsi cd ~se fait dans un sous-shell, et pwddans un sous-shell séparé
donc vous obtiendrez seulement le STDOUT à partir pwdd'où vous exécutez la commande, cela peut être n'importe quel répertoire comme vous pouvez l'imaginer, donc pcontiendra le nom du répertoire d'où la commande est invoquée, pas votre répertoire personnel
À quoi sert le canal entre les commandes? cd ~ne produit aucune sortie et pwdne lit aucune entrée.
Barmar
La deuxième commande est essentiellement équivalente à (cd ~);p=$(pwd)non?
Barmar
@Barmar Oui, c'est ce qu'OP a utilisé, et je l'explique juste pour lui.
heemayl
7
Le problème principal est de savoir comment les opérateurs &&et |connecter les deux commandes.
Le &&connecte les commandes via le code de sortie. Le |connecte les deux commandes via les descripteurs de fichiers (stdin, stdout).
Simplifions d'abord. Nous pouvons supprimer l'affectation et écrire:
echo $(cd ~&& pwd)
echo $(cd ~| pwd)
Nous pouvons même supprimer le sous-shell d'exécution de commande pour analyser ceci:
$ cd ~&& pwd
$ cd ~| pwd
&&
Si nous changeons l'invite pour afficher le répertoire où les commandes sont exécutées, quelque chose comme PS1='\w\$ ', nous verrons ceci:
/tmp/user$ cd ~&& pwd
/home/user
~$
La commande a cd ~changé le "répertoire actuel" au domicile de l'utilisateur réel qui exécute la commande ( /home/user).
Comme le résultat de la commande a réussi (code de sortie 0), la commande suivante après l'exécution du &&
Et le "répertoire de travail actuel" est imprimé.
La coque en cours d' exécution a changé pwdà ~comme le montre l'invite de ~$.
Si le changement de répertoire a échoué (code de sortie non 0) pour une raison quelconque (le répertoire n'existe pas, les autorisations bloquent la lecture du répertoire), la commande suivante ne sera pas exécutée.
Exemple:
/tmp/user$ false && pwd
/tmp/user$ _
Le code de sortie de 1 falseempêche l'exécution de la commande suivante.
Ainsi, le code de sortie de la "commande 1" est ce qui affecte la "commande 2".
Le répertoire a été modifié, mais à l'intérieur d'un sous-shell $(…), le répertoire modifié est imprimé /home/user, mais est immédiatement supprimé à la fermeture du sous-shell. Le pwd redevient le répertoire initial ( /tmp/user).
|
Voici ce qui se passe:
/tmp/user$ cd ~| pwd
/tmp/user
/tmp/user$ _
Le méta-caractère |(pas un véritable opérateur) signale au shell de créer ce qu'on appelle un "Pipe", (en bash) chaque commande de chaque côté du pipe ( |) est définie à l'intérieur de chaque sous-shell, d'abord le côté droit commande, puis, celui de gauche. Le descripteur de fichier d'entrée ( /dev/stdin) de la commande de droite est connecté au descripteur de sortie ( /dev/stdout), puis les deux commandes sont démarrées et laissées pour interagir. La commande gauche ( cd -) n'a pas de sortie et, également, la commande droite ( pwd) n'accepte aucune entrée. Ainsi, chacun s'exécute indépendamment à l'intérieur de chaque sous-shell.
Le cd ~change le pwd d'un shell.
Le pwdimprime le (complètement indépendant) pwd de l'autre sous-shell.
Les modifications sur chaque coque sont rejetées lorsque le tuyau se termine, la sous-coque externe n'a pas changé le pwd.
C'est pourquoi les deux commandes ne sont connectées que par des "descripteurs de fichiers".
Dans ce cas, rien n'est envoyé et rien n'est lu.
La commande entière:
$ echo "$(cd ~ | pwd)"
Imprime simplement le répertoire où la commande a été exécutée.
Je ne sais pas si tu voulais dire '|' ou '||' dans votre deuxième cas.
«|» dans un shell dirige la sortie d'une commande vers l'entrée d'une autre - un cas d'utilisation courant ressemble à:
curl http://abcd.com/efgh | grep ijkl
exécuter une commande et utiliser une autre commande pour traiter la sortie d'une commande.
Dans l'exemple que vous donnez, il est assez absurde, car «cd» ne génère généralement aucune sortie et «pwd» n'attend aucune entrée.
«&&» et «||» sont des commandes partenaires cependant. Ils sont conçus pour être utilisés de la même manière que les opérateurs logiques "et" et "ou" dans la plupart des langues. Cependant, les optimisations qui sont effectuées leur donnent un comportement spécifique qui est un paradigme de programmation shell.
Pour déterminer le résultat d'une opération logique "et", il vous suffit d'évaluer la deuxième condition si la première condition réussit - si la première condition échoue, le résultat global sera toujours faux.
Pour déterminer le résultat d'une opération logique "ou", il vous suffit d'évaluer la deuxième condition si la première condition échoue - si la première condition réussit, le résultat global sera toujours vrai.
Donc, dans le shell, si vous command1 && command2command2ne serez exécuté que lorsque vous aurez command1terminé et retourné un code de résultat réussi. Si vous avez command1 || command2command2sera exécuté à la command1fin si command1renvoie un code d'échec.
Un autre paradigme commun est d'avoir command1une commande de test - cela génère une seule instruction if / then de ligne - par exemple:
[ "$VAR" = "" ] && VAR="Value if empty"
Est une manière (longue) d'affecter une valeur à une variable si elle est actuellement vide.
Il existe de nombreux exemples d'utilisation de ce processus ailleurs sur Stack Exchange
|
exécution en sous-coquilles.Réponses:
Dans
p=$(cd ~ && pwd)
:La substitution de commande
$()
, s'exécute en sous-shellcd ~
change le répertoire en~
(votre home), sicd
réussit (&&
) puispwd
imprime le nom du répertoire sur STDOUT, donc la chaîne sauvegardéep
sera votre répertoire home par exemple/home/foobar
Dans
p=$(cd ~ | pwd)
:$()
Génère à nouveau un sous-shellLes commandes des deux côtés de la
|
course dans les sous-coquilles respectives (et les deux démarrent en même temps)ainsi
cd ~
se fait dans un sous-shell, etpwd
dans un sous-shell séparédonc vous obtiendrez seulement le STDOUT à partir
pwd
d'où vous exécutez la commande, cela peut être n'importe quel répertoire comme vous pouvez l'imaginer, doncp
contiendra le nom du répertoire d'où la commande est invoquée, pas votre répertoire personnella source
cd ~
ne produit aucune sortie etpwd
ne lit aucune entrée.(cd ~);p=$(pwd)
non?Le problème principal est de savoir comment les opérateurs
&&
et|
connecter les deux commandes.Le
&&
connecte les commandes via le code de sortie. Le|
connecte les deux commandes via les descripteurs de fichiers (stdin, stdout).Simplifions d'abord. Nous pouvons supprimer l'affectation et écrire:
Nous pouvons même supprimer le sous-shell d'exécution de commande pour analyser ceci:
&&
Si nous changeons l'invite pour afficher le répertoire où les commandes sont exécutées, quelque chose comme
PS1='\w\$ '
, nous verrons ceci:cd ~
changé le "répertoire actuel" au domicile de l'utilisateur réel qui exécute la commande (/home/user
).pwd
à~
comme le montre l'invite de~$
.Si le changement de répertoire a échoué (code de sortie non 0) pour une raison quelconque (le répertoire n'existe pas, les autorisations bloquent la lecture du répertoire), la commande suivante ne sera pas exécutée.
Exemple:
Le code de sortie de 1
false
empêche l'exécution de la commande suivante.Ainsi, le code de sortie de la "commande 1" est ce qui affecte la "commande 2".
Maintenant, les effets de toute la commande:
Le répertoire a été modifié, mais à l'intérieur d'un sous-shell
$(…)
, le répertoire modifié est imprimé/home/user
, mais est immédiatement supprimé à la fermeture du sous-shell. Le pwd redevient le répertoire initial (/tmp/user
).|
Voici ce qui se passe:
Le méta-caractère
|
(pas un véritable opérateur) signale au shell de créer ce qu'on appelle un "Pipe", (en bash) chaque commande de chaque côté du pipe (|
) est définie à l'intérieur de chaque sous-shell, d'abord le côté droit commande, puis, celui de gauche. Le descripteur de fichier d'entrée (/dev/stdin
) de la commande de droite est connecté au descripteur de sortie (/dev/stdout
), puis les deux commandes sont démarrées et laissées pour interagir. La commande gauche (cd -
) n'a pas de sortie et, également, la commande droite (pwd
) n'accepte aucune entrée. Ainsi, chacun s'exécute indépendamment à l'intérieur de chaque sous-shell.cd ~
change le pwd d'un shell.pwd
imprime le (complètement indépendant) pwd de l'autre sous-shell.Les modifications sur chaque coque sont rejetées lorsque le tuyau se termine, la sous-coque externe n'a pas changé le pwd.
C'est pourquoi les deux commandes ne sont connectées que par des "descripteurs de fichiers".
Dans ce cas, rien n'est envoyé et rien n'est lu.
La commande entière:
Imprime simplement le répertoire où la commande a été exécutée.
la source
Je ne sais pas si tu voulais dire '|' ou '||' dans votre deuxième cas.
«|» dans un shell dirige la sortie d'une commande vers l'entrée d'une autre - un cas d'utilisation courant ressemble à:
curl http://abcd.com/efgh | grep ijkl
exécuter une commande et utiliser une autre commande pour traiter la sortie d'une commande.Dans l'exemple que vous donnez, il est assez absurde, car «cd» ne génère généralement aucune sortie et «pwd» n'attend aucune entrée.
«&&» et «||» sont des commandes partenaires cependant. Ils sont conçus pour être utilisés de la même manière que les opérateurs logiques "et" et "ou" dans la plupart des langues. Cependant, les optimisations qui sont effectuées leur donnent un comportement spécifique qui est un paradigme de programmation shell.
Pour déterminer le résultat d'une opération logique "et", il vous suffit d'évaluer la deuxième condition si la première condition réussit - si la première condition échoue, le résultat global sera toujours faux.
Pour déterminer le résultat d'une opération logique "ou", il vous suffit d'évaluer la deuxième condition si la première condition échoue - si la première condition réussit, le résultat global sera toujours vrai.
Donc, dans le shell, si vous
command1 && command2
command2
ne serez exécuté que lorsque vous aurezcommand1
terminé et retourné un code de résultat réussi. Si vous avezcommand1 || command2
command2
sera exécuté à lacommand1
fin sicommand1
renvoie un code d'échec.Un autre paradigme commun est d'avoir
command1
une commande de test - cela génère une seule instruction if / then de ligne - par exemple:[ "$VAR" = "" ] && VAR="Value if empty"
Est une manière (longue) d'affecter une valeur à une variable si elle est actuellement vide.
Il existe de nombreux exemples d'utilisation de ce processus ailleurs sur Stack Exchange
la source