Можно получить свободный экземпляр на Amazon EC2 в течение года. Просто зарегистрируйте и создайте t1.micro экземпляр, который довольно способен к выполнению достойного небольшого веб-сайта.
Вот более простая альтернатива:
$(compgen -c libreoffice)
предполагает, что Bash и предполагает, что есть только один LibreOffice *
.
Это эмулирует то, что завершение вкладок Bash будет делать, если вы набрали вкладку LibreOffice
.
Если вы сознательно пытаетесь исключить LibreOffice
без номера версии, и хотите обрабатывать существование нескольких версий, попробуйте:
run_libreoffice() {
compgen -c libreoffice |
while read -r exe; do
case "$exe" in libreoffice?.?)
"$exe" "$@"
return
;;
esac
done
}
run_libreoffice "$@"
Оператор Case
делает его совпадение LibreOffice?.?
, и мы циклируем по результатам, только бегу только первым.
Установите
: :
: : : , чтобы разделить значение пути
на двоеточиях. Если ваш Найти
, имеет --Кайт
----Кактеп
и -MaxDepth
Primary (например, FreeBSD, OSX, GNU), вы знаете, что команда будет существовать, и вы не T Ухаживать за кодом возврата команды, вы можете использовать этот одноклассник:
pattern='libreoffice?.?'
IFS=:; find $PATH -maxdepth 1 -type f -name "$pattern" -exec {} \; -quit; unset IFS
Это не обеспечивает простого способа сообщить, была ли была найдена команда. Кроме того, быть более надежным, отключить глобуску в случае, если значение PATH
содержит подстановочные знаки. Кроме того, можно иметь пустой компонент в пути
, чтобы означать текущий каталог (но мой совет должен использовать .
вместо). Код ниже заботится обо всех этих осложнениях.
pattern='libreoffice?.?'
case $PATH in
:*) directories=.$PATH;;
*::*) directories=${PATH%%::*}:.:${PATH#*::};;
*:) directories=$PATH.;;
*) directories=$PATH;;
esac
set -f; IFS=:
cmd=
for d in $directories; do
set +f
for x in "$d"/$pattern; do
if [ -x "$x" ] && ! [ -d "$x" ]; then
cmd=$x
break
fi
done
if [ -n "$cmd" ]; then break; fi
done
set +f; unset IFS
if [ -z "$cmd" ]; then
echo 1>&2 "$pattern: not found in PATH"
exit 127
else
exec "$cmd"
fi
Если вы будете использовать ZSH (в отличие от простого SH, Bash, KSH, ...), это намного проще сделать надежное решение.
pattern='libreoffice?.?'
matches=($^path/$~pattern(N.*[1]))
if ((!#matches)); then
$matches[1]
else
echo 1>&2 "$pattern: not found in PATH"
exit 127
fi
Вы можете использовать команду «найти» следующим образом
find ./ -name "libreoffice?.?"
с ZSH
:
$commands[(i)libreoffice?.?]
в ZSH
, $ Команды
- это специальный ассоциативный массив, клавиши которых являются названиями команд и значение их пути.
I
выше представляет собой флаг подделок , который говорит ZSH
, чтобы соответствовать шаблону на клавишах массива и вернуть первую подходящую клавишу.
Элементы ассоциативного массива не в каком-либо конкретном порядке, хотя, поэтому сначала соответствующий ключ не обязательно будет первым, что происходит в $ PATH
. Если вы хотите LibreOffice
с наибольшим числом версии, вы можете сделать:
${${(nO)${commands[(I)libreoffice?.?]}}[1]}
Флаг I
Flags расширяется до всех соответствующих клавиш. Мы используем N
(численное сортировка), а o
(обратный порядок) флаги расширения параметров , чтобы сортировать этот список от наибольшего до наименьшего номера версии, а затем [1]
Чтобы выбрать первый.
См. Также:
whence -m 'libreoffice?.?'
Чтобы найти пути соответствующих команд.
POSIX: при поиске $ PATH
исполняемого файла команды следует использовать команду
:
команду -v
Если вызывается без переключателя, команда
вызовет имя_команды , но вам все равно нужен полностью разрешенный путь для полного разрешения глобуса оболочки .
Итак, чтобы сделать это, вы должны проверить глобус для каждого элемента :
, разделенного двоеточием, в $ PATH
в порядке, как spec'd :
PATH
:
. Когда к этому имени файла применяется префикс ненулевой длины, между префиксом и именем файла должна быть вставлена косая черта. Префикс нулевой длины - это унаследованная функция , которая указывает текущий рабочий каталог. Он отображается как два соседних двоеточия ::
, как начальное двоеточие перед остальной частью списка или как конечное двоеточие после остальной части списка. Строго соответствующее приложение должно использовать фактическое имя пути (например, .
) для представления текущего рабочего каталога в PATH
. Список должен просматриваться от начала до конца, применяя имя_файла к каждому префиксу, пока не будет найден исполняемый файл с указанным именем и соответствующими разрешениями на выполнение. Если искомый путь содержит косую черту, поиск по префиксам пути выполняться не будет. Если путь начинается с косой черты, указанный путь разрешается (см. Разрешение пути ) . Если ПУТЬ
не задан или установлен в ноль, поиск пути определяется реализацией . Вы можете разделить $ PATH
на поле для каждого компонента $ PATH
на $ IFS
, но вы можете сделать только это безопасно, если вы также установили -f
расширение имени файла как отключенное, пока вы это делаете, в случае, если компонент в $ PATH
содержит любой из [? *
символов , потому что генерация имени файла (читай: подстановка) происходит после разделения полей в порядке расширения оболочки.
Таким образом, в общем, единственный действительно надежный способ сделать это POSIXly - сначала развернуть список полей на $ IFS
, когда генерация имени файла отключена, и каким-то образом сохранить результат этого массива, а затем еще раз включите создание имени файла и отключите разделение полей (чтобы вы могли хранить и расширять свой шаблон глобуса без кавычек в переменной без какой-либо опасности того, что на него повлияет $ IFS
first) , и обрабатываем каждый результат по очереди.
К счастью, это не так уж и сложно:
g='libreoffice?.?'
( IFS=:; set-f #split on :; disable filename gen
set +f -- $PATH #store split array, enable filename gen after
IFS= #disable field splitting
for p do for x in ${p:+"$p/"$g}
do command -v "$x"
done;done
) #done in subshell to avoid affecting current shell
Последние части не комментируются, потому что здесь они лучше объяснены.
for p do
- Первый цикл for
итеративно присваивает $ p
значение каждого позиционного параметра в «$ @» оболочки
массив , которые устанавливают
как разделенное по полям расширение $ PATH
, разделенное на :
двоеточия.
for x в $ {p: + "$ p /" $ g}
- Внутренний цикл for
итеративно устанавливает $ x
для каждого (если any) расширений $ {p: + "$ p /" $ g}
- то есть, он не выполняет итерации вообще ничего, если только $ p
не является оба установлены и не равны нулю. Это важно, потому что ::
или ведущий :
будет разделен на пустые поля, и, таким образом, два цикла строго соответствуют ] $ PATH
spec (как указано выше) , не подтверждая поля нулевой длины .
Важно отметить, что из-за способа разделения $ PATH
, когда генерация имени файла отключена, и «$ p /» $ g
разрешается, пока он включен, но разделение полей было отключен, ни один из элементов в $ PATH
не может расширяться до чего-либо, кроме их полей, разделенных на :
(независимо от того, какие другие символы они могут содержать) , и ни одно из значений не может for "$ p /" $ g
расширяется до чего угодно, кроме самого себя или любых имен файлов, которые могут совпадать (независимо от любых символов в $ p
или отличных от символов сопоставления с образцом $ g
может содержать) .
команда
- и последняя команда
печатает в стандартном формате только те значения для $ x
, которые являются исполняемыми командами.
Вот все, что заключено в функцию оболочки с дополнительной возможностью обработки нескольких $ g
аргументов:
glob_path()(
for g do IFS=:; set -f
set +f -- ${PATH:-.}; IFS=
for p do for x in ${p:+"$p/"$g}
do command -v "$x"
done; done; done
)
Это должно дать вам список исполняемых файлов, соответствующих каждому аргументу, который вы передаете, напечатанный по одному на каждый Строка упорядочена сначала по порядку аргументов, затем по приоритету $ PATH
и в последнюю очередь по порядку сортировки вашего языкового стандарта. Он не должен давать сбоев при переводе строки или специальных символах в именах путей или шаблонах глобусов, которые вы ему передаете. Его можно изменить (см. Историю редактирования здесь) , чтобы точно заполнить массив оболочки «$ @»
одним исполняемым файлом для каждого позиционного параметра.
Вы также можете изменить его, чтобы выполнить первое успешное совпадение glob и прекратить поиск этого конкретного аргумента glob и перейти к следующему, если команда завершится успешно, например ...
glob_path()(
for g do IFS=:; set -f
set +f -- ${PATH:-.}; IFS=
for p do for x in ${p+:"$p/"$g}
do command -v "$x" &&
command "$x" &&
break 2
done; done; done
)
Это портативное средство POSIX для поиска вашего glob, но некоторым оболочкам даже не нужен второй цикл for g ...
. В bash
, например, это также будет работать как ...
glob_path()(
for g do IFS=:; set -f
set +f -- ${PATH:-.}; IFS=
for p do command -v ${p:+"$p/"$g}
done; done
)
... который по-прежнему перечисляет все совпадения исполняемых глобусов для всех аргументов и для каждого элемента в $ PATH
независимо от о том, содержат ли какие-либо из этих элементов или шаблонов глобусов символы новой строки, специальные символы и т. д.
Вы можете использовать это как:
glob_path '?sh' '??sh' #I'd rather not install libreoffice
... который для меня печатает ...
/usr/bin/ksh
/usr/bin/rsh
/usr/bin/ssh
/usr/bin/zsh
/usr/local/bin/dash
/usr/local/bin/yash
/usr/bin/bash
/usr/bin/bssh
/usr/bin/chsh
/usr/bin/dash
/usr/bin/mksh
/usr/bin/posh
/usr/bin/slsh
/usr/bin/yash
Как уже обсуждалось, функция glob_path
интерпретирует переменную среды $ PATH
, поскольку в спецификации указано, что строго соответствующее приложение должно игнорировать начальные, конечные или последовательные :
встречается в значении $ PATH
, но интерпретирует пустой или неустановленный $ PATH
как означающий .
.
Однако, если вам нужна эта устаревшая функция, функцию можно было бы написать:
glob_path()(
for g do IFS=:; set -f
set +f -- ${0+$PATH:}; IFS=
for p do for x in "${p:-.}/"$g
do command -v "$x"
done; done; done
)
... которая интерпретировала бы все вхождения начальных, конечных или двух последовательных :
двоеточий как означающих .
(и поэтому ищите .
столько раз, сколько компонент нулевой длины $ PATH
появляется в значении $ PATH
) , но это не совсем соответствует.