Respuestas:
¿Hay alguna razón histórica para que haya dos comandos en lugar de uno?
Solo había manera de la historia.
printenvcomando en 1979 para BSD.envcomando en 1980.enven 1986.enven 1988.printenven 1988.printenven 1989.printenvy enven 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ó printenvesa vez, el envtodaví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 envcasos de uso se comparan con printenv:
printenvpueden hacer lo mismoenablecmd.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 pythonencabezado, pero aún no es portátil si envno 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.shpara 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.shy env -i bash /tmp/test.shvuelva a ejecutar . Si algo falla, deshazlo. Repita el paso para reducir. [5] Finalmente, me doy cuenta de que es eognecesario $DISPLAYcorrer crontab, y ausente $DBUS_SESSION_BUS_ADDRESSdisminuirá 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 envo 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 envse 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)envcomando apareció en 4.4BSD. Las opciones -P, -S y -v se agregaron en FreeBSD 6.0. El printenvcomando apareció en 3.0BSD. Entonces, la razón histórica parece ser que printenvllegó 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.
printenvsolo imprime todas las variables del entorno actual. Con envusted puede preparar el mismo entorno con algunas modificaciones si es necesario y ejecutar una aplicación en él.
lses un binario, pero lles un alias común, que generalmente solo se expande a ls -l. printenvy envson 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, enves un binario con un gran conjunto de características, una de ellas es la impresión de variables de entorno, mientras que printenvsolo imprime variables de entorno.
Resumiendo, si estás acostumbrado a trabajar con env, irás enva imprimirlos (porque a eso estás acostumbrado) y si no lo estás, normalmente recordarás printenvmás rápido.
Prácticamente no hay diferencias cuando se habla de printenvvs envsolo 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í.