Risposte:
Ci sono ragioni storiche per cui ci sono due comandi anziché uno?
C'era solo la storia.
printenvcomando nel 1979 per BSD.envcomando nel 1980.envnel 1986.envnel 1988.printenvnel 1988.printenvnel 1989.printenve envnel 1991.Si noti che il "seguito" non significa che il codice sorgente fosse lo stesso, probabilmente sono stati riscritti per evitare una causa di licenza.
Quindi la ragione per cui esistevano entrambi i comandi è perché quando Bill Joy scrisse printenvquella volta, il envnon esiste ancora. Dopo 10 anni di fusione / compatibilità e GNU, ora vedi entrambi i comandi simili nella stessa pagina.
Questa cronologia indicava quanto segue: (Provo a ridurre al minimo la risposta e quindi fornisce solo 2 codice sorgente essenziale qui, il resto è possibile fare clic sui collegamenti allegati per vedere)
[autunno del 1975]
Arrivarono nell'autunno del 1975 anche due dottorandi inosservati, Bill Joy e Chuck Haley; entrambi si interessarono immediatamente al nuovo sistema. Inizialmente iniziarono a lavorare su un sistema Pascal che Thompson aveva violato insieme mentre gironzolava nella sala macchine 11/70.
[1977]
Joy iniziò a compilare la prima Berkeley Software Distribution (1BSD), che fu rilasciata il 9 marzo 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Febbraio 1979]
1979 (vedi "Bill Joy, UCB February, 1979") / 1980 (vedi "copyright [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? file = 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 da determinare rilasciato in 2BSD O 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD Il comando printenv è apparso in 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD introdotto al 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD Il comando printenv è apparso per la prima volta in 2BSD // rf: http://man.openbsd.org/printenv.1
[Giugno 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 primo manuale printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 ma non riesco a trovare il manuale relativo a env , il più vicino è getenv e environment // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Prima versione di 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 rilasciato // 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 ottobre 1988]
MINIX versione 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c esistono già
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Prima versione di GNU printenv, fare riferimento a [12 agosto 1993].
[16 luglio 1991]
"Shellutils" - Rilasciate le utility di programmazione della shell GNU 1.0 // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
I programmi in questo pacchetto sono:
basename data dirname env expr gruppi id logname pathchk printenv printf sleep tee tty whoami sì nice nohup stty uname
[12 agosto 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 che ha trovato sul codice sorgente DSLinux nel 2006 // rf: (Google) cache: 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 prima versione di FreeBSD è stata rilasciata. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1 settembre 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
I pacchetti fileutils, textutils e sh-utils GNU (vedi "Shellutils" al 16 luglio 1991 sopra) sono stati uniti in uno, chiamato coreutils GNU.
Complessivamente, i envcasi d'uso si confrontano con printenv:
printenvpuò fare lo stessoenablefarlo anche con cmd.impostare variabile ma inutile a causa di alcune shell già può farlo senza env, ad es
$ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env pythonintestazione, ma comunque non portatile se envnon in / usr / bin
env -i, disabilita tutto env. Ho trovato utile capire le variabili di ambiente critiche per determinati programmi per eseguirlo crontab. es. [1] In modalità interattiva, esegui declare -p > /tmp/d.shper memorizzare le variabili degli attributi. [2] In /tmp/test.sh, scrivi: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg[3] Ora esegui env -i bash /tmp/test.sh[4] Se riesce a visualizzare l'immagine, rimuovi metà delle variabili /tmp/d.shed esegui di env -i bash /tmp/test.shnuovo. Se qualcosa non ha funzionato, annullalo. Ripetere il passaggio per restringere. [5] Alla fine ho capito che eogbisogna $DISPLAYcorrere crontab, e in assenza di $DBUS_SESSION_BUS_ADDRESSciò rallenterà la visualizzazione dell'immagine.
target_PATH="$PATH:$(sudo printenv PATH)";è utile per utilizzare direttamente il percorso di root senza dover analizzare ulteriormente l'output di envo printenv.
per esempio:
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:~$
Avendo un diverso punto di vista (da FreeBSD), hai:
Da 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.
Da 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.
Quindi questi comandi potrebbero avere lo stesso effetto senza argomenti, ma l' printenvunico scopo è quello di visualizzare la chiave / i valori dell'ambiente corrente mentre l' envobiettivo è di impostare un ambiente prima di chiamare un altro binario / script / qualunque cosa.
È più chiaro in questo modo?
Per saperne di più:
man 1 env (FreeBSD)man 1 printenv (FreeBSD)envcomando è apparso in 4.4BSD. Le opzioni -P, -S e -v sono state aggiunte in FreeBSD 6.0. Il printenvcomando è apparso in 3.0BSD. Quindi la ragione storica sembra essere quella printenvarrivata per prima.
Dalle pagine man:
env - esegue un programma in un ambiente modificato
...
printenv - stampa tutto o parte dell'ambiente
Dovrebbe essere piuttosto esplicativo.
printenvstampa solo tutte le variabili dell'ambiente corrente. Con envte puoi preparare lo stesso ambiente con alcune modifiche se necessario ed eseguire un'app al suo interno.
lsè un file binario, ma llè un alias comune, che di solito si espande ls -l. printenve envsono due binari diversi, non sono sicuro di quale sia stato introdotto per primo però. Puoi vedere altri esempi qui gnu.org/software/coreutils/manual/html_node/env-invocation.html
Parlando rigorosamente di funzionalità, envè un file binario con una vasta gamma di funzionalità, una delle quali è la stampa di variabili d'ambiente, mentre printenvstampa solo variabili d'ambiente.
Riassumendo, se sei abituato a lavorare con env, andrai avanti con envla loro stampa (perché è quello a cui sei abituato) e se non lo sei, in genere ti ricorderai printenvpiù velocemente.
Non ci sono praticamente differenze quando si parla di printenvvs envsolo per la stampa di variabili ambientali. Ho appena controllato ed env è leggermente più pesante (circa 5 KB in più) e le loro prestazioni (nel tempo) sembrano essere esattamente le stesse.
Spero che questo lo chiarisca! :)
Se vuoi davvero sapere quanto è diverso l'output dei due binari indipendentemente dalla storia e dall'eredità di essi, puoi eseguire alcune utility per valutare questa differenza. Su debian ho eseguito alcune cose che saranno diverse a seconda di eventuali variabili ambientali personalizzate:
env |wc -l
printenv |wc -l
Entrambi i miei output hanno 41 righe
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Uscita: 41c41 <_ = / usr / bin / env ---
_ = / Usr / bin / printenv
Quindi vedi che c'è una linea diversa nelle due e quella linea è il numero 41 che immagino stabilisce il binario usato nel comando. Senza ulteriori argomenti, questi riportano informazioni identiche virtuali per me.