Réponses:
Y a-t-il des raisons historiques pour qu'il y ait deux commandes au lieu d'une?
Il y avait juste la manière de l'histoire.
printenv
commande en 1979 pour BSD.env
commandement en 1980.env
en 1986.env
en 1988.printenv
en 1988.printenv
en 1989.printenv
et env
en 1991.Notez que le mot "suivi" ne signifie pas que le code source était le même, ils ont probablement été réécrits pour éviter une poursuite en licence.
La raison pour laquelle les deux commandes existaient est donc parce que lorsque Bill Joy a écrit printenv
cette époque, le env
n'existe pas encore. Après 10 ans de fusion / compatibilité et de GNU, vous voyez maintenant les deux commandes similaires sur la même page.
Cet historique indique comme suit: (J'essaie de minimiser la réponse et ne fournit donc que 2 codes sources essentiels ici, le reste vous pouvez cliquer sur les liens attachés pour voir)
[automne 1975]
Arrivés à l’automne 1975, Bill Joy et Chuck Haley, deux étudiants diplômés de troisième cycle, ont également été remarqués. ils ont tous deux un intérêt immédiat pour le nouveau système. Initialement, ils ont commencé à travailler sur un système Pascal que Thompson avait piraté ensemble pendant qu'ils traînaient dans la salle des machines 11/70.
[1977]
Joy a commencé à compiler la première version de Berkeley Software Distribution (1BSD), sortie le 9 mars 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Février 1979]
1979 (voir "Bill Joy, UCB février 1979") / 1980 (voir "copyright [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? fichier = 2.11BSD / src / ucb / printenv.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif not lint
#ifndef lint
static char sccsid[] = "@(#)printenv.c 5.1 (Berkeley) 5/31/85";
#endif not lint
/*
* printenv
*
* Bill Joy, UCB
* February, 1979
*/
extern char **environ;
main(argc, argv)
int argc;
char *argv[];
{
register char **ep;
int found = 0;
argc--, argv++;
if (environ)
for (ep = environ; *ep; ep++)
if (argc == 0 || prefix(argv[0], *ep)) {
register char *cp = *ep;
found++;
if (argc) {
while (*cp && *cp != '=')
cp++;
if (*cp == '=')
cp++;
}
printf("%s\n", cp);
}
exit (!found);
}
prefix(cp, dp)
char *cp, *dp;
{
while (*cp && *dp && *cp == *dp)
cp++, dp++;
if (*cp == 0)
return (*dp == '=');
return (0);
}
[1979]
Difficile à déterminer publié dans 2BSD OU 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD La commande printenv est apparue dans la version 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD introduit en 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD La commande printenv est apparue pour la première fois dans 2BSD // rf: http://man.openbsd.org/printenv.1
[Juin 1980]
UNIX version 3.0 OU "UNIX System III" // rf: ftp://pdp11.org.ru/pub/unix-archive/PDP-11/Distributions/usdl/SysIII/
[xiaobai@xiaobai pdp11v3]$ sudo grep -rni printenv . //no such printenv exist.
[xiaobai@xiaobai pdp11v3]$ sudo find . -iname '*env*'
./sys3/usr/src/lib/libF77/getenv_.c
./sys3/usr/src/lib/libc/vax/gen/getenv.c
./sys3/usr/src/lib/libc/pdp11/gen/getenv.c
./sys3/usr/src/man/man3/getenv.3c
./sys3/usr/src/man/docs/c_env
./sys3/usr/src/man/docs/mm_man/s03envir
./sys3/usr/src/man/man7/environ.7
./sys3/usr/src/man/man1/env.1
./sys3/usr/src/cmd/env.c
./sys3/bin/env
[xiaobai@xiaobai pdp11v3]$ man ./sys3/usr/src/man/man1/env.1 | cat //but got env already
ENV(1) General Commands Manual ENV(1)
NAME
env - set environment for command execution
SYNOPSIS
env [-] [ name=value ] ... [ command args ]
DESCRIPTION
Env obtains the current environment, modifies it according to its arguments, then executes the command with the modified environment. Arguments of the form
name=value are merged into the inherited environment before the command is executed. The - flag causes the inherited environment to be ignored completely,
so that the command is executed with exactly the environment specified by the arguments.
If no command is specified, the resulting environment is printed, one name-value pair per line.
SEE ALSO
sh(1), exec(2), profile(5), environ(7).
ENV(1)
[xiaobai@xiaobai pdp11v3]$
[xiaobai@xiaobai pdp11v3]$ cat ./sys3/usr/src/cmd/env.c //diff with http://minnie.tuhs.org/cgi-bin/utree.pl?file=pdp11v/usr/src/cmd/env.c version 1.4, you will know this file is slightly older, so we can concluded that this file is "env.c version < 1.4"
/*
* env [ - ] [ name=value ]... [command arg...]
* set environment, then execute command (or print environment)
* - says start fresh, otherwise merge with inherited environment
*/
#include <stdio.h>
#define NENV 100
char *newenv[NENV];
char *nullp = NULL;
extern char **environ;
extern errno;
extern char *sys_errlist[];
char *nvmatch(), *strchr();
main(argc, argv, envp)
register char **argv, **envp;
{
argc--;
argv++;
if (argc && strcmp(*argv, "-") == 0) {
envp = &nullp;
argc--;
argv++;
}
for (; *envp != NULL; envp++)
if (strchr(*envp, '=') != NULL)
addname(*envp);
while (*argv != NULL && strchr(*argv, '=') != NULL)
addname(*argv++);
if (*argv == NULL)
print();
else {
environ = newenv;
execvp(*argv, argv);
fprintf(stderr, "%s: %s\n", sys_errlist[errno], *argv);
exit(1);
}
}
addname(arg)
register char *arg;
{
register char **p;
for (p = newenv; *p != NULL && p < &newenv[NENV-1]; p++)
if (nvmatch(arg, *p) != NULL) {
*p = arg;
return;
}
if (p >= &newenv[NENV-1]) {
fprintf(stderr, "too many values in environment\n");
print();
exit(1);
}
*p = arg;
return;
}
print()
{
register char **p = newenv;
while (*p != NULL)
printf("%s\n", *p++);
}
/*
* s1 is either name, or name=value
* s2 is name=value
* if names match, return value of s2, else NULL
*/
static char *
nvmatch(s1, s2)
register char *s1, *s2;
{
while (*s1 == *s2++)
if (*s1++ == '=')
return(s2);
if (*s1 == '\0' && *(s2-1) == '=')
return(s2);
return(NULL);
}
[xiaobai@xiaobai pdp11v3]$
[1985]
Premier manuel d'impression BSD // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 mais je n'ai pas trouvé de manuel relatif à env , le plus proche est getenv et environ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Première version de GNU env
// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/env.c
[1987]
MINIX 1ere sortie // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum
[1988]
BSD 1st env.c // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/usr.sbin/cron/env.c
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* All rights reserved
[4 octobre 1988]
MINIX version 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c existe déjà
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Première version de GNU printenv
, voir [12 août 1993].
[16 juillet 1991]
"Shellutils" - Publication de la version 1.0 des utilitaires de programmation du shell GNU // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Les programmes de ce paquet sont:
nom de base date dirname env env groupes id id logname pathchk printenv printf sommeil tee tty whoami oui gentil nohup stty uname
[12 août 1993]
printenv.c // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/printenv.c
, GNU Shell Utilities 1.8 // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/VERSION
/* printenv -- print all or part of environment
Copyright (C) 1989, 1991 Free Software Foundation.
...
[1993]
printenv.c qui a trouvé le code source DSLinux en 2006 // rf: cache (Google): mailman.dslinux.in-berlin.de/pipermail/dslinux-commit-dslinux.in-berlin.de/2006-August/000578. html
--- NEW FILE: printenv.c ---
/*
* Copyright (c) 1993 by David I. Bell
[Novembre 1993]
La première version de FreeBSD a été publiée. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1er septembre 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
Les paquets GN fileutils, textutils et sh-utils (voir "Shellutils" au 16 juillet 1991 ci-dessus) ont été fusionnés en un seul, appelé GNU coreutils.
Dans l’ensemble, env
les cas d’utilisation se comparent avec printenv
:
printenv
peut en faire autantenable
cmd aussi.définir variable mais inutile en raison de certains coquilles peut déjà le faire sans env
, par exemple
$ HOME = / dev HOME = / tmp UTILISATEUR = racine / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
en-tête, mais toujours pas portable sinon env
dans / usr / bin
env -i
, désactivez toutes les env. J'ai trouvé utile de déterminer les variables d'environnement critiques pour que certains programmes l'exécutent crontab
. Exemple: [1] En mode interactif, exécuter declare -p > /tmp/d.sh
pour stocker les variables d'attribut. [2] Dans /tmp/test.sh
, écrivez: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Maintenant, exécutez env -i bash /tmp/test.sh
[4] Si vous réussissez à afficher une image, supprimez la moitié des variables /tmp/d.sh
et exécutez-le à env -i bash /tmp/test.sh
nouveau. Si quelque chose a échoué, annulez-le. Répétez cette étape pour affiner. [5] Enfin, je comprends qu'il eog
faut $DISPLAY
courir crontab
, et sans $DBUS_SESSION_BUS_ADDRESS
ralentir l'affichage de l'image.
target_PATH="$PATH:$(sudo printenv PATH)";
est utile pour utiliser directement le chemin racine sans avoir à analyser plus avant le résultat de env
ou printenv
.
par exemple:
xb@dnxb:~$ sudo env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
xb@dnxb:~$ sudo printenv | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
xb@dnxb:~$ sudo printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
xb@dnxb:~$ sudo env PATH
env: ‘PATH’: No such file or directory
xb@dnxb:~$
Ayant un point de vue différent (de FreeBSD), vous avez:
De man env
:
The env utility executes another utility after modifying the environment
as specified on the command line. Each name=value option specifies the
setting of an environment variable, name, with a value of value. All
such environment variables are set before the utility is executed.
...
If no utility is specified, env prints out the names and values of the
variables in the environment, with one name/value pair per line.
De man printenv
:
The printenv utility prints out the names and values of the variables in
the environment, with one name/value pair per line. If name is speci-
fied, only its value is printed.
Donc, ces commandes peuvent avoir le même effet sans argument, mais le printenv
seul but est d’afficher la clé / les valeurs de l’environnement actuel tout en env
visant à définir un environnement avant d’appeler un autre binaire / script / peu importe.
Est-ce plus clair de cette façon?
Pour en savoir plus:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
commande est apparue dans 4.4BSD. Les options -P, -S et -v ont été ajoutées dans FreeBSD 6.0. La printenv
commande est apparue dans 3.0BSD. Donc, la raison historique semble être celle qui printenv
est arrivée en premier.
env
est POSIX 7 ,printenv
n’est pas (GNU Coreutils dans Ubuntu 15.10).
Des pages de manuel:
env - lance un programme dans un environnement modifié
...
printenv - imprime tout ou partie de l'environnement
Devrait être assez explicatif.
printenv
n'imprime que toutes les variables de l'environnement actuel. Avec env
vous pouvez préparer le même environnement avec quelques modifications si nécessaire et y exécuter une application.
ls
est un binaire, mais ll
est un alias commun, qui se développe généralement en ls -l
. printenv
et env
sont deux binaires différents, je ne suis pas sûr de savoir lequel a été introduit en premier. Vous pouvez voir quelques exemples supplémentaires ici gnu.org/software/coreutils/manual/html_node/env-invocation.html
Parler strictement de fonctionnalités, env
est un binaire avec un vaste ensemble de fonctionnalités, l’une d’elles étant l’impression de variables d’environnement, alors printenv
qu’il n’imprime que les variables d’environnement.
En résumé, si vous avez l'habitude de travailler avec env, vous irez les env
imprimer (parce que c'est ce que vous avez l'habitude de faire) et si vous ne l'êtes pas, vous vous en souviendrez printenv
plus rapidement.
Il n'y a pratiquement aucune différence entre printenv
vs env
et simplement imprimer des variables environnementales. Je viens de vérifier et env est légèrement plus lourd (environ 5 Ko supplémentaires), et leur performance (dans le temps) semble être exactement la même.
J'espère que ça efface! :)
Si vous voulez vraiment savoir en quoi les résultats des deux fichiers binaires sont différents, indépendamment de leur historique et de leur héritage, vous pouvez exécuter quelques utilitaires pour évaluer cette différence. Sur debian, j’ai fait quelques choses qui seront différentes selon les vars environnementaux personnalisés:
env |wc -l
printenv |wc -l
Ma sortie a 41 lignes
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Sortie: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
Donc, vous voyez qu'il y a une ligne différente dans les deux et que cette ligne est le numéro 41 qui, je suppose, stipule le binaire utilisé dans la commande. Sans arguments supplémentaires, ceux-ci rapportent des informations virtuellement identiques pour moi.