Respuestas:
¿Hay alguna razón histórica para que haya dos comandos en lugar de uno?
Solo había manera de la historia.
printenv
comando en 1979 para BSD.env
comando en 1980.env
en 1986.env
en 1988.printenv
en 1988.printenv
en 1989.printenv
y env
en 1991.Tenga en cuenta que "seguido" no significa que el código fuente era el mismo, probablemente fueron reescritos para evitar una demanda de licencia.
Entonces, la razón de por qué ambos comandos existieron es porque cuando Bill Joy escribió printenv
esa vez, el env
todavía no existe. Después de 10 años de fusión / compatibilidad y GNU lo encuentra, ahora está viendo ambos comandos similares en la misma página.
Este historial indica lo siguiente: (Intento minimizar la respuesta y, por lo tanto, solo proporciono 2 códigos fuente esenciales aquí, el resto puede hacer clic en los enlaces adjuntos para ver)
[otoño de 1975]
También llegaron en el otoño de 1975 dos estudiantes graduados inadvertidos, Bill Joy y Chuck Haley; Ambos se interesaron de inmediato por el nuevo sistema. Inicialmente comenzaron a trabajar en un sistema Pascal que Thompson había pirateado mientras se paseaba por la sala de máquinas 11/70.
[1977]
Joy comenzó a compilar el primer Berkeley Software Distribution (1BSD), que se lanzó el 9 de marzo de 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Febrero de 1979]
1979 (ver "Bill Joy, UCB febrero, 1979") / 1980 (ver "copyright [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? archivo = 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]
Difícil de determinar publicado en 2BSD O 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD El comando printenv apareció en 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD introducido en 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD El comando printenv apareció por primera vez en 2BSD // rf: http://man.openbsd.org/printenv.1
[Junio de 1980]
UNIX Release 3.0 O "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]
BSD first printenv manual // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 pero no encuentro el manual relacionado con env , el más cercano es getenv y environmental // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Primera versión 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 1st lanzado // 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 de octubre de 1988]
MINIX versión 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c ya existen
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Primera versión de GNU printenv
, consulte [12 de agosto de 1993].
[16 de julio de 1991]
"Shellutils" - Utilidades de programación de shell GNU 1.0 lanzadas // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Los programas en este paquete son:
basename date dirname env expr grupos id logname pathchk printenv printf sleep tee tty whoami sí nice nohup stty uname
[12 de agosto de 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 que se encontró en el código fuente de DSLinux en 2006 // rf: (Google) caché: 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
[Noviembre de 1993]
Se lanzó la primera versión de FreeBSD. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1 de septiembre de 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
Los paquetes GNU fileutils, textutils y sh-utils (ver "Shellutils" al 16 de julio de 1991 arriba) se han fusionado en uno, llamado GNU coreutils.
En general, los env
casos de uso se comparan con printenv
:
printenv
pueden hacer lo mismoenable
cmd.establecer variable pero sin sentido debido a que algunos shells ya pueden hacerlo sin env
, por ejemplo
$ HOME = / dev HOME = / tmp USUARIO = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
encabezado, pero aún no es portátil si env
no está en / usr / bin
env -i
, deshabilitar todo env. Me resultó útil descubrir las variables de entorno críticas para que cierto programa lo ejecute crontab
. ej. [1] En modo interactivo, ejecutar declare -p > /tmp/d.sh
para almacenar variables de atributos. [2] En /tmp/test.sh
, escriba: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Ahora ejecute env -i bash /tmp/test.sh
[4] Si tiene éxito para mostrar la imagen, elimine la mitad de las variables /tmp/d.sh
y env -i bash /tmp/test.sh
vuelva a ejecutar . Si algo falla, deshazlo. Repita el paso para reducir. [5] Finalmente, me doy cuenta de que es eog
necesario $DISPLAY
correr crontab
, y ausente $DBUS_SESSION_BUS_ADDRESS
disminuirá la visualización de la imagen.
target_PATH="$PATH:$(sudo printenv PATH)";
es útil para usar directamente la ruta raíz sin tener que analizar más la salida de env
o printenv
.
p.ej:
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:~$
Teniendo un punto de vista diferente (de FreeBSD), tiene:
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.
Por lo tanto, estos comandos pueden tener el mismo efecto sin argumento, pero el printenv
único propósito es mostrar la clave / valores del entorno actual mientras env
se establece un entorno antes de llamar a otro binario / script / lo que sea.
¿Está más claro de esta manera?
Para saber más:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
comando apareció en 4.4BSD. Las opciones -P, -S y -v se agregaron en FreeBSD 6.0. El printenv
comando apareció en 3.0BSD. Entonces, la razón histórica parece ser que printenv
llegó primero.
env
es POSIX 7 ,printenv
no lo es (GNU Coreutils en Ubuntu 15.10).
De páginas de manual:
env: ejecuta un programa en un entorno modificado
...
printenv - imprime todo o parte del entorno
Debería ser bastante explicativo.
printenv
solo imprime todas las variables del entorno actual. Con env
usted puede preparar el mismo entorno con algunas modificaciones si es necesario y ejecutar una aplicación en él.
ls
es un binario, pero ll
es un alias común, que generalmente solo se expande a ls -l
. printenv
y env
son dos binarios diferentes, aunque no estoy seguro de cuál se introdujo primero. Puede ver algunos ejemplos más aquí gnu.org/software/coreutils/manual/html_node/env-invocation.html
Hablando estrictamente de funcionalidades, env
es un binario con un gran conjunto de características, una de ellas es la impresión de variables de entorno, mientras que printenv
solo imprime variables de entorno.
Resumiendo, si estás acostumbrado a trabajar con env, irás env
a imprimirlos (porque a eso estás acostumbrado) y si no lo estás, normalmente recordarás printenv
más rápido.
Prácticamente no hay diferencias cuando se habla de printenv
vs env
solo para imprimir variables ambientales. Acabo de comprobar y env es un poco más pesado (aproximadamente 5 KB adicionales), y su rendimiento (a tiempo) parece ser exactamente el mismo.
Espero que esto lo aclare! :)
Si realmente desea saber qué tan diferente es la salida de los dos binarios, independientemente del historial y el legado de los mismos, puede ejecutar algunas utilidades para medir esta diferencia. En Debian ejecuté algunas cosas que serán diferentes dependiendo de cualquier variable ambiental personalizada:
env |wc -l
printenv |wc -l
Tanto mi salida tiene 41 líneas
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Salida: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
Entonces ves que hay una línea diferente en las dos y esa línea es la número 41, que supongo que estipula el binario utilizado en el comando. Sin argumentos adicionales, estos informan información virtual idéntica para mí.