Вы можете выполнять их параллельно с помощью ... gnu parallel:
parallel "sh script.sh {} > {}.out" ::: *
То же самое происходит и в Emacs Lisp. Он имеет два пространства имен, одно для функций и одно для переменных. Если вы разыменовываете символ в контексте функции ((var)
), он вызовет функцию, если вы разыменовываете его в контексте переменной (var
, то есть без скобок ), он даст вам переменную. Например:
(defun myvar (myvar)
"adds 3 to MYVAR"
(+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))
Выполнит функцию myvar
с аргументом 7
, который является разыменованием переменной myvar
.
Это может стать очень запутанным, если вы к этому не привыкли.
Посмотрев на ваш вопрос и проведя тесты для bash , я удивлен, что он демонстрирует такое же поведение. Перевод ELisp сверху на bash:
[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10
Bash немного менее запутан в этом, чем ELisp, потому что вам нужен $
, чтобы пометить переменную. Тем не менее, это может выглядеть как declare
одного имени, состоящего из двух вещей. См.:
[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar ()
{
echo $(($1+3))
}
(П.С. Как только вы привыкнете к существованию двух пространств имен, например. вы программируете на ELisp какое-то время, это перестает сбивать с толку)
Обычно оболочки различают переменные и функции, потому что они используются в разных контекстах. В двух словах, имя является именем переменной, если оно появляется после $
или в качестве аргумента встроенных функций, таких какexport
(без-f
)иunset
(без-f
). Имя является именем функции, если оно появляется как команда (после раскрытия псевдонима )или как аргумент для export -f
, unset -f
и т. д.
Переменные можно экспортировать в среду. Имя переменной среды такое же, как и у переменной оболочки (, и значения такие же ).
Bash, в отличие от большинства других оболочек, также может экспортировать функции в среду. Поскольку в среде нет индикации типа, нет никакого способа узнать, является ли запись в среде функцией или нет, кроме как путем анализа имени или значения переменной среды.
Старые версии bash хранили функцию в среде, используя имя функции в качестве имени и что-то похожее на определение функции в качестве значения функции. Например:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Обратите внимание, что невозможно отличить функцию с кодом { echo foobar; }
от переменной со значением () { echo foobar}
(, где 
— символ новой строки ). Это оказалось неудачным дизайнерским решением.
Иногда сценарии оболочки вызываются с переменными среды, значение которых находится под контролем потенциально враждебной сущности. Например, CGI-скрипты. Функция экспорта/импорта функций Bash позволяла вводить функции таким образом. Например, выполнение скрипта
#!/bin/bash
ls
из удаленного запроса безопасен, если среда не содержит переменных с определенным именем (, напримерPATH
). Но если запрос может установить переменную среды ls
в () { cat /etc/passwd; }
, тогда bash с радостью выполнит cat /etc/passwd
, поскольку это тело функции ls
.
Эта уязвимость системы безопасности была обнаружена Стефаном Шазела как один из аспектов ошибки Shellshock . В версиях bash после -Shellshock экспортированные функции идентифицируются по имени , а не по содержимому.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
Теперь нет проблем с безопасностью, потому что такие имена, как BASH_FUNC_foobar%%
, обычно не используются в качестве имен команд и могут быть отфильтрованы интерфейсами, которые позволяют передавать переменные среды.Технически возможно иметь символ %
в имени переменной окружения (, это то, что заставляет работать экспортируемые функции современного bash ), но обычно люди этого не делают, потому что оболочки не принимают %
в имя переменной.
Предложение в руководстве bash относится к старому поведению (до -Shellshock ). Его следует обновить или удалить. В современных версиях bash в среде нет двусмысленности, если вы предполагаете, что переменные среды не будут иметь имя, оканчивающееся на %%
.