Відповіді:
Чи є історичні причини того, що замість однієї є дві команди?
Існувала просто манера історії.
printenv
команди в 1979 році для BSD.env
командування в 1980 році.env
у 1986 році.env
у 1988 році.printenv
У 1988 році MINIX послідував за BSD .printenv
у 1989 році.printenv
і env
в 1991 році.Зауважте, що "слідував" не означає, що вихідний код був однаковим, ймовірно, вони були переписані, щоб уникнути позовів про ліцензію.
Тож причина, чому обидві команди існували, полягає в тому, що коли Білл Джой писав printenv
той час, її env
ще не існує. Після 10 років злиття / сумісності та GNU натрапив на нього, ви зараз бачите обидві подібні команди на одній сторінці.
Ця історія вказується так: (Я намагаюся мінімізувати відповідь, і так надається тут лише 2 основних вихідних коду, решта ви можете натиснути додані посилання, щоб побачити)
[осінь 1975]
Також восени 1975 року прибули двоє непомічених аспірантів, Білл Джой та Чак Хейлі; вони обоє негайно зацікавились новою системою. Спочатку вони почали працювати над системою Паскаля, яку Томпсон зламав разом, розвішуючи машинну кімнату 11/70.
[1977]
Радість почала складати перший дистрибутив програмного забезпечення Берклі (1BSD), який вийшов 9 березня 1978 року. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Лютий, 1979]
1979 р. (Див. "Білл Радість, УКБ лютого 1979 р.") / 1980 р. (Див. "Авторське право [] ="), 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]
Важко визначити випущений у 2BSD АБО 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD Команда printenv з'явилася в 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD, введений у 1979 році // rf: http://gunkies.org/wiki/3_BSD
2BSD Команда printenv вперше з'явилася в 2BSD // rf: http://man.openbsd.org/printenv.1
[Червень 1980 р.]
Випуск UNIX 3.0 АБО "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 // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1, але я не можу знайти посібник, пов'язаний з env , найближчим є getenv та середовище // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Перша версія GNU env
// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/env.c
[1987]
MINIX 1-го випуску // 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 жовтня 1988 р.]
MINIX версія 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c вже існує
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Перша версія GNU printenv
, див. [12 серпня 1993].
[16 липня 1991 р.]
"Shellutils" - випущені утиліти програмування оболонки GNU // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Програми цього пакету:
базове ім'я dirname env expr групи id ім'я ім'я pathchk printenv printf сон tee tty whoami так добре nohup stty unme
[12 серпня 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, який був знайдений у вихідному коді DSLinux у 2006 році // rf: (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
[Листопад 1993 р.]
Перша версія FreeBSD була випущена. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1 вересня 2002 р.]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
Пакети файлів, текстилів та ш-утилів GNU (див. "Shellutils" 16 липня 1991 року вище) пакети були об'єднані в один, який називається coreutils GNU.
Загалом, env
випадки використання порівняно з printenv
:
printenv
можуть робити те самеenable
cmd.встановити змінну, але безглуздо, оскільки деякі оболонки вже можуть це зробити env
, наприклад,
$ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
заголовок, але все ще не портативний, якщо env
не в / usr / bin
env -i
, відключити всі env Мені здалося корисним визначити критичні змінні середовища для певної програми, щоб змусити її працювати crontab
. наприклад [1] В інтерактивному режимі запустіть declare -p > /tmp/d.sh
до зберігання змінних атрибутів. [2] /tmp/test.sh
Впишіть: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Тепер запустіть env -i bash /tmp/test.sh
[4] Якщо це вдасться відобразити зображення, видаліть половину змінних у /tmp/d.sh
та запустіть env -i bash /tmp/test.sh
ще раз. Якщо щось не вдалося, скасуйте це. Повторіть крок для звуження. [5] Нарешті я з'ясував, що eog
потрібно $DISPLAY
запустити crontab
, а відсутність $DBUS_SESSION_BUS_ADDRESS
уповільнить показ зображення.
target_PATH="$PATH:$(sudo printenv PATH)";
корисно для прямого використання кореневого шляху без необхідності подальшого розбору результатів env
або printenv
.
наприклад:
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:~$
Маючи іншу точку зору (від FreeBSD), у вас є:
Від 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.
Від 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.
Таким чином, ці команди можуть мати той самий ефект без аргументу, але printenv
єдиною метою є відображення поточного ключа / значень середовища, в той час як env
його встановити деяке середовище перед тим, як викликати інший бінарний / скрипт / будь-який інший.
Чи більш зрозуміло це?
Щоб знати більше:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
printenv
printenv
З довідкових сторінок:
env - запуск програми в модифікованому середовищі
...
printenv - друкує все або частину середовища
Повинно бути досить пояснювальним.
printenv
просто друкує всі змінні поточного середовища. З env
ви можете приготувати в ту ж середу з деякими змінами , в разі необхідності і запустити додаток в ньому.
ls
є двійковим, але ll
є загальним псевдонімом, який зазвичай просто розширюється ls -l
. printenv
і env
це два різні бінарні файли, я не впевнений, який із них було введено першим. Ще кілька прикладів ви можете подивитися тут gnu.org/software/coreutils/manual/html_node/env-invocation.html
Якщо говорити строго про функціональні можливості, env
це двійковий файл з величезним набором функцій, однією з яких є змінні середовища друку, тоді як printenv
просто друкує змінні середовища.
Підводячи підсумок, якщо ви звикли працювати з env, ви підете env
на їх друк (адже саме до цього ви звикли), а якщо цього не зробите, ви зазвичай запам'ятаєте printenv
швидше.
Практично немає відмінностей, якщо говорити про printenv
vs env
для просто друку змінних навколишнього середовища. Я щойно перевірив, і env трохи важче (близько 5 зайвих КБ), а їх продуктивність (за часом) здається точно такою ж.
Сподіваюся, це очистить це! :)
Якщо ви дійсно хочете знати, наскільки різний вихід двох бінарних файлів незалежно від історії та спадщини їх, ви можете запустити кілька утиліт, щоб оцінити цю різницю. На Debian я запустив кілька речей, які будуть відрізнятися залежно від будь-яких спеціальних екологічних варіантів:
env |wc -l
printenv |wc -l
Обидва мої результати мають 41 рядок
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Вихід: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
Таким чином, ви бачите, що у двох є один рядок, і цей рядок є номером 41, який, напевно, визначає двійковий код, який використовується в команді. Без додаткових аргументів ці звіти повідомляють віртуальну ідентичну для мене інформацію.