Я "сломал" свою систему, добавив записи в FSTAB для моих локальных томов, например:
# /etc/fstab
#
# This file is read once by the first process in a Cygwin process tree.
# To pick up changes, restart all Cygwin processes. For a description
# see https://cygwin.com/cygwin-ug-net/using.html#mount-table
# This is default anyway:
none /cygdrive cygdrive binary,posix=0,user 0 0
c:/ /c ntfs text,posix=0 0 0
d:/ /d ntfs text,posix=0 0 0
f:/ /f ntfs text,posix=0 0 0
g:/ /g ntfs text,posix=0 0 0
Я «отремонтировал» его, изменив fstab на:
none /cygdrive cygdrive binary,posix=0,user 0 0
none /tmp usertemp binary,posix=0 0 0
c:/ /c ntfs binary,posix=0,cygexec 0 0
d:/ /d ntfs binary,posix=0,cygexec 0 0
f:/ /f ntfs binary,posix=0,cygexec 0 0
g:/ /g ntfs binary,posix=0,cygexec 0 0
Я думаю, что произошло то, что, не монтируя 4 диска (c, d, f, g) как «exec», каждый раз, когда cygwin искал внешний it открыл и прочитал большое количество файлов в поисках «волшебных» байтов, чтобы узнать, является ли файл исполняемым.
Между тем, mintty буферизовала то, что я ввел как «тип вперед», пока я не вышел с Ctrl-C, убивая все еще выполняющийся поиск моей команды.
Добавив "cygexec" к параметрам, поиск теперь обращается только к исполняемым флагам в каталогах и выполняется на полной скорости.
Это эквивалентно:
( export someVariable=something; command )
Это делает someVariable
переменной окружения, с присвоенным значением, но только для выполняемой команды.
Вот соответствующие части руководства по bash
:
Простые команды
Простая команда - это последовательность необязательных назначений переменных, за которыми следуют разделенные пробелами слова и перенаправления, а завершается она оператором управления. Первое слово определяет команду, которая должна быть выполнена, и передается как нулевой аргумент. Остальные слова передаются в качестве аргументов вызываемой команды.
(...)
Простое расширение команд
Если в результате расширения команд не возникает имени команды, то назначения переменных влияют на текущее окружение оболочки. В противном случае переменные добавляются к окружению выполняемой команды и не влияют на текущее окружение оболочки.
Примечание: имейте в виду, что это не специфично для bash
, а определено POSIX.
Редактировать - Обобщенное обсуждение из комментариев в ответе
Причина, по которой BAZ=JAKE echo $BAZ
, не выводит JAKE, заключается в том, что подстановка переменных выполняется до всего остального. Если обойти подстановку переменных, то все будет как ожидалось:
$ echo_baz() { echo "[$BAZ]"; }
$ BAZ=Jake echo_baz
[Jake]
$ echo_baz
[]
Здесь происходит несколько ключевых вещей:
Как объясняется в справочном руководстве bash , Простая команда Расширение, раздел «Если имя команды не дается, присвоение переменных влияет на текущую среду оболочки. В противном случае переменные добавляются в среду выполняемой команды и не влияют на текущую среду оболочки». Таким образом, когда вы говорите var = "something" command arg1 arg2
, команда будет выполняться, когда var
находится в среде команды и исчезает после выхода команды
. Демонстрация этого проста - доступ к среде команды из команды:
$ BAZ = "jake" python -c "import os; print os.environ ['BAZ']"
jake {{1 }}
Ничего удивительного. Такой синтаксис часто используется для запуска программ в модифицированной среде. Мои коллеги, пользователи unix.stackexchange.com и askubuntu.com, узнают этот пример: если пользователь использует немецкий язык, а вы говорите только по-английски, вы можете попросить их воспроизвести любую проблему, с которой они столкнулись, и получить вывод на английском языке следующим образом:
LC_ALL = команда C
Обратите внимание, что доступ к среде не является специфическим для python
. Это можно сделать с помощью C
или любого другого языка программирования.Так уж получилось, что сейчас он был моим «любимым оружием» и использовался только для этой демонстрации.
Расширение переменной происходит перед запуском чего-либо. Таким образом, когда вы запускаете что-то вроде BAZ = "foo" echo $ BAZ
, оболочка сначала просматривает свою среду, не находит там переменной BAZ и, таким образом, оставляет $ BAZ
пустым. Простая демонстрация этого:
$ BAZ = "jake" python -c "import sys; print 'ARG:', sys.argv [1]" $ BAZ
ARG:
Traceback (последний вызов последним):
Файл "", строка 1, в
IndexError: список индекса вне допустимого диапазона
Также важно обратите внимание, отличие от BAZ = jake; echo $ BAZ
, который представляет собой два отдельных командных оператора, и здесь BAZ = jake
останется в среде оболочки. Вариант использования зависит от ваших намерений. Если вы намереваетесь запустить несколько программ, которым нужна такая переменная, может быть желательно экспортировать
такую переменную. Если вам это нужно только в этот конкретный момент, то предыдущее присвоение переменных может быть предпочтительнее.
Простыми словами:
BAZ=jake echo $BAZ
ничего не выводит, потому что подстановка переменной
выполняется первой в команде. Это означает, что первое, что происходит в этой командной строке, - это $ BAZ
будет заменено любым фактическим значением, с которым ранее была определена переменная BAZ
(если таковая имеется). Учтите, что это происходит еще до того, как оболочка считает BAZ = jake
в той же командной строке.
Перед выполнением нашей команды, поскольку BAZ
не имеет присвоенного значения и поскольку BAZ = jake
рассматривается только после разрешения $ BAZ
, $ BAZ
не принимает никакого значения. Следовательно, echo $ BAZ
ничего не выводит.
BAZ = jake
- это только часть данной команды (оболочка не будет рассматривать / устанавливать ее как переменную среды). Это наиболее полезно, если некоторый процесс, выполняемый как часть той же командной строки, использует эту переменную BAZ
. Значение BAZ
, jake
является непостоянным после завершения выполнения команды.
Например: ] # LD_LIBRARY_PATH = "new_path" ldconfig
, где команда ldconfig
внутренне ссылается на переменную LD_LIBRARY_PATH
, и в этой команде нет расширения переменной линия в отличие от выше.
Для другого случая:
BAZ=jake; echo $BAZ
Это две разные команды, указанные в одной строке. Это так же хорошо, как выполнять одно за другим.
Это назначения переменных в контексте простых команд. Как упоминал xhienne, для внешних команд они эквивалентны экспорту присвоенного значения (значений) на время выполнения команды.
В ваших примерах вы используете встроенную команду, поэтому поведение не совсем такое же: присваивания влияют на текущее окружение, но сохраняется ли эффект после выполнения встроенной команды, не уточняется. Чтобы понять ваши примеры, нужно знать, что расширение параметров происходит до обработки переменных; так, с
BAZ=jake echo $BAZ
shell сначала расширяет $BAZ
(в результате ничего не получается), затем устанавливает BAZ
в jake
, и, наконец, выполняет
echo
которая печатает пустую строку. (Затем оболочка забывает BAZ
, как показывает последующее echo $BAZ
).
BAZ=jake; echo $BAZ
интерпретируется как две команды: сначала переменная BAZ
устанавливается в текущем окружении, затем echo $BAZ
расширяется до echo jake
и выполняется.