Часто задаваемые вопросы
Что эквивалентно этому элементу из bash (или других оболочек)?
Как задать или очистить переменную окружения?
Используйте команду set:
set -x key value # typically set -gx key value set -e key
С версии fish 3.1 вы можете установить переменную окружения только для одной команды, используя синтаксис key=value some command, как и в других оболочках. Две строки ниже ведут себя идентично — в отличие от других оболочек, fish выведет value в обоих случаях:
key=value echo $key begin; set -lx key value; echo $key; end
Обратите внимание, что «exported» не является областью видимости, а дополнительной частью состояния. Переменная может быть глобальной и экспортированной, локальной и экспортированной или даже универсальной и экспортированной. Обычно имеет смысл сделать экспортированную переменную глобальной.
Как проверить, определена ли переменная?
Используйте set -q var. Например, if set -q var; echo variable defined; end. Чтобы проверить несколько переменных, вы можете комбинировать их с and и or следующим образом:
if set -q var1; or set -q var2
echo either variable defined
end
Помните, что определенная переменная также может быть пустой, либо не имея элементов (если установлена как set var) или содержа только пустые элементы (если установлена как set var ""). Продолжайте читать, чтобы узнать, как с этим справиться.
Как проверить, что переменная не пуста?
Используйте string length -q -- $var. Например, if string length -q -- $var; echo not empty; end. Обратите внимание, что string length интерпретирует список из нескольких переменных как дизъюнкцию (т. е. любое/или):
if string length -q -- $var1 $var2 $var3
echo at least one of these variables is not empty
end
В качестве альтернативы используйте test -n "$var", но помните, что переменная должна быть заключена в двойные кавычки. Например, if test -n "$var"; echo not empty; end. Команда test предоставляет свои собственные and (-a) и or (-o):
if test -n "$var1" -o -n "$var2" -o -n "$var3"
echo at least one of these variables is not empty
end
Если вы хотите узнать, содержит ли переменная никаких элементов, используйте set -q var[1].
Почему не работает set -Ux (экспортированные универсальные переменные)?
Уже существует глобальная переменная с тем же именем.
Переменные окружения, такие как EDITOR или TZ, могут быть установлены универсально с помощью set -Ux Однако, если переменная окружения уже установлена до запуска fish (например, скриптами входа или системными администраторами), она импортируется в fish как глобальная переменная. Области видимости переменных переменных проверяются «изнутри наружу», что означает, что локальные переменные проверяются первыми, за ними следуют глобальные переменные, а затем универсальные переменные.
Это означает, что глобальное значение имеет приоритет над универсальным значением.
Чтобы избежать этой проблемы, рассмотрите возможность изменения настроек, которые наследует fish. Если это невозможно, добавьте оператор в ваш конфигурационный файл (обычно ~/.config/fish/config.fish):
set -gx EDITOR vim
Как выполнить команду при каждом входе? Какой эквивалент fish для .bashrc или .profile?
Отредактируйте файл ~/.config/fish/config.fish 1, создав его, если он не существует (обратите внимание на ведущую точку).
В отличие от .bashrc и .profile, этот файл всегда читается, даже в неинтерактивных или логин-оболочках.
Чтобы сделать что-то только в интерактивных оболочках, проверьте status is-interactive следующим образом:
if status is-interactive
# use the coolbeans theme
fish_config theme choose coolbeans
end
-
1 -
Часть «~/.config» может быть задана через $XDG_CONFIG_HOME, это просто по умолчанию.
Как настроить свой приглашающий символ?
Приглашающий символ — это вывод функции fish_prompt. Разместите его в ~/.config/fish/functions/fish_prompt.fish. Например, простым приглашением является:
function fish_prompt
set_color $fish_color_cwd
echo -n (prompt_pwd)
set_color normal
echo -n ' > '
end
Вы также можете использовать веб-инструмент конфигурации fish_config, чтобы просмотреть и выбрать из галереи образцов приглашений.
Или вы можете использовать fish_config из командной строки:
> fish_config prompt show # displays all the prompts fish ships with > fish_config prompt choose disco # loads the disco prompt in the current shell > fish_config prompt save # makes the change permanent
Если вы хотите изменить существующее приглашение, вы можете использовать funced и funcsave следующим образом:
>_ funced fish_prompt # This opens up your editor (set in $EDITOR). # Modify the function, # save the file and repeat to your liking. # Once you are happy with it: >_ funcsave fish_prompt
Это также относится к fish_right_prompt и fish_mode_prompt.
Почему мой приглашающий символ отображает [I]?
Это fish_mode_prompt. Он отображается по умолчанию, когда вы активировали режим vi с помощью fish_vi_key_bindings.
Если вы не активировали режим vi намеренно, возможно, вы установили стороннюю тему или плагин, который это делает.
Если вы хотите изменить или отключить это отображение, измените функцию fish_mode_prompt, например, с помощью funced.
Как настроить цвета подсветки синтаксиса?
Используйте веб-инструмент конфигурации fish_config или измените семейство переменных окружения fish_color.
Вы также можете использовать fish_config в командной строке, например:
> fish_config theme show # to demonstrate all the colorschemes > fish_config theme choose coolbeans # to load the "coolbeans" theme > fish_config theme save # to make the change permanent
Как изменить приветственное сообщение?
Измените значение переменной fish_greeting или создайте функцию fish_greeting. Например, чтобы удалить приветствие, используйте:
set -U fish_greeting
Или, если вы предпочитаете не использовать универсальную переменную, используйте:
set -g fish_greeting
в config.fish.
Как запустить команду из истории?
Введите часть команды, а затем нажмите клавиши со стрелками вверх ↑ или вниз ↓ для перемещения по совпадениям в истории. Дополнительные стандартные сочетания клавиш включают Control+P (вверх) и Control+N (вниз). Более подробную информацию см. в поиске в истории команд.
Почему не работает подстановка истории («!$» и т. д.)?
Потому что подстановка истории — это неудобный интерфейс, который был разработан до того, как стал возможен интерактивный редактор строк. Вместо добавления этого псевдосинтаксиса, fish предлагает удобные функции поиска и восстановления истории. Переключение требует небольших изменений привычек: если вы хотите изменить старую строку/слово, сначала восстановите ее, а затем отредактируйте.
Как особый случай, в большинстве случаев подстановка истории используется как sudo !!. В этом случае просто нажмите Alt+S, и он восстановит вашу последнюю командную строку с префиксом sudo (или переключит префикс sudo в текущей командной строке, если есть что-то).
В общем, восстановление истории в fish работает так:
- Как и в других оболочках, стрелка вверх ↑ восстанавливает целые строки, начиная с последней выполненной строки. Одно нажатие заменяет «!!», последующие нажатия заменяют «!-3» и т. д.
- Если нужная строка находится далеко в истории, введите любую ее часть, а затем нажмите клавишу вверх один или несколько раз. Это отфильтрует восстановленные строки, содержащие этот текст, и вы быстрее дойдете до нужной строки. Это заменяет «!vi», «!?bar.c» и т. д.
- Alt+↑ восстанавливает отдельные аргументы, начиная с последнего аргумента в последней выполненной строке. Одно нажатие заменяет «!$», последующие нажатия заменяют «!!:4» и т. д. В качестве альтернативного сочетания клавиш можно использовать Alt+..
- Если нужный аргумент находится далеко в истории (например, 2 строки назад — это много слов!), введите любую его часть, а затем нажмите Alt+↑. Это отобразит только аргументы, содержащие эту часть, и вы быстрее получите нужное. Попробуйте, это очень удобно!
- Если вы хотите повторно использовать несколько аргументов из одной строки («!!:3*» и т. д.), рассмотрите возможность восстановления всей строки и удаления ненужных элементов (Alt+D и Alt+Backspace — ваши друзья).
Более подробную информацию об интерактивном редактировании строк в fish см. в документации.
Как выполнить подкоманду? Символ обратной кавычки не работает!
fish использует скобки для подкоманд. Например:
for i in (ls)
echo $i
end
Он также поддерживает знакомый синтаксис $() даже в кавычках. Символы обратной кавычки не поддерживаются, потому что они не рекомендуются даже в оболочках POSIX. Они плохо вложены и трудно отличимы от одинарных кавычек ('').
Моя команда (pkg-config) выдаёт результат как одну длинную строку?
В отличие от других оболочек, fish разделяет подстановки команд только по символам новой строки, а не пробелам, табуляции или символам в $IFS.
Это означает, что если вы выполните
count (printf '%s ' a b c)
Она напечатает 1, потому что «a b c » используется как одно целое. Но если вы сделаете
count (printf '%s\n' a b c)
Она напечатает 3, потому что она передала count аргументы «a», «b» и «c» по отдельности.
В подавляющем большинстве случаев разделение по пробелам нежелательно, поэтому это улучшение. Именно поэтому вы слышите о проблемах с именами файлов, содержащими пробелы.
Однако иногда, особенно с pkg-config и связанными инструментами, разделение по пробелам необходимо.
В этих случаях используйте string split -n " " , например:
g++ example_01.cpp (pkg-config --cflags --libs gtk+-2.0 | string split -n " ")
-n настолько пуста, что пустые элементы удаляются, как это делают оболочки POSIX.
Как получить код возврата команды?
Используйте переменную $status. Это замена переменной $?, используемой в других оболочках.
somecommand
if test $status -eq 7
echo "That's my lucky number!"
end
Если вас интересует только успех или неудача, вы можете выполнить команду непосредственно как условие if:
if somecommand
echo "Command succeeded"
else
echo "Command failed"
end
Или, если вы хотите выполнить одну команду в случае успеха или неудачи первой, используйте and или or.
somecommand or someothercommand
См. Условные операторы и документацию для test и if для получения дополнительной информации.
Моя команда выводит «No matches for wildcard», но работает в bash
Короче: цитируйте или экранируйте символ подстановки:
scp user@ip:/dir/"string-*"
Когда fish видит нецитированную *, она выполняет расширение подстановок. Это означает, что она пытается сопоставить имена файлов с данной строкой.
Если символ подстановки не соответствует никаким файлам, fish выводит ошибку вместо запуска команды:
> echo *this*does*not*exist
fish: No matches for wildcard '*this*does*not*exist'. See `help expand`.
echo *this*does*not*exist
^
Теперь bash также пытается сопоставить файлы в этом случае, но когда не находит совпадения, он передает буквально строку символа подстановки вместо неё.
Это означает, что команды, подобные вышеприведённым
scp user@ip:/dir/string-*
или
apt install postgres-*
кажутся работающими, потому что в большинстве случаев строка не совпадает, и поэтому она передаёт string-*, которая затем интерпретируется принимающей программой.
Но это также означает, что эти команды могут перестать работать в любой момент, как только будет встречен соответствующий файл (потому что он был создан или команда выполняется в другой рабочей директории), и для решения этой проблемы bash нуждается в обходных путях, таких как
for f in ./*.mpg; do
# We need to test if the file really exists because
# the wildcard might have failed to match.
test -f "$f" || continue
mympgviewer "$f"
done
(из http://mywiki.wooledge.org/BashFAQ/004)
По этим причинам fish не делает этого и вместо этого ожидает, что звёздочки будут цитированы или экранированы, если они не должны быть расширены.
Это аналогично параметру «failglob» в bash.
Я случайно ввёл путь к директории, и fish сменил директорию. Что произошло?
Если fish не может найти команду с заданным именем, и она начинается с ., / или ~, fish проверит, существует ли директория с таким именем. Если существует, она предположит, что вы хотите изменить свою директорию. Например, самый быстрый способ перейти в домашнюю директорию — просто нажать ~ и нажать Enter.
Команда open не работает.
Команда open использует базу данных MIME-типов и файлы .desktop, используемые Gnome и KDE, для определения типов файлов и стандартных действий. Если хотя бы одна из этих сред установлена, но команда open не работает, это, вероятно, означает, что соответствующие файлы установлены в нестандартном месте. Подумайте о поиске дополнительной помощи.
Почему SSH/SCP/rsync не подключаются должным образом, когда fish — моя оболочка входа?
Эта проблема может проявляться как сообщения, такие как «Received message too long», «open terminal
failed: not a terminal», «Bad packet length» или «Connection refused» со странным выводом в ssh_exchange_identification сообщениях в журнале отладки.
Это обычно происходит, потому что fish всегда считывает файл конфигурации пользователя файл конфигурации пользователя (~/.config/fish/config.fish), независимо от того, является ли оболочка интерактивной, оболочкой входа или нет.
Это упрощает задачу, но это также означает, что когда config.fish генерирует вывод, она делает это даже в неинтерактивных оболочках, таких как те, которые ssh/scp/rsync запускают при подключении.
Всё, что в config.fish производит вывод, должно быть защищено с помощью status is-interactive (или status is-login, если вы предпочитаете):
if status is-interactive ... end
То же самое относится, например, к запуску tmux в config.fish без защит, что приведёт к сообщению, такому как sessions should be nested with care, unset $TMUX to force.
У меня появляются странные графические артефакты (эффект лестницы, призрачные символы, курсор в неправильном положении)?
В терминале приложение, работающее внутри него, и сам терминал должны договориться о ширине символов для обработки перемещения курсора.
Это для fish важнее, чем для других оболочек, потому что такие функции, как подсветка синтаксиса и автодополнение, реализуются путём перемещения курсора.
Иногда наблюдается несогласие по ширине. Причин и решений для этого множество:
- Возможным является то, что символ слишком новый для системы, которая его знает, — в этом случае вы должны воздержаться от его использования.
- Fish или ваш терминал могут не знать о символе или обрабатывать его неправильно — в этом случае необходимо исправить fish или ваш терминал, либо обновиться до исправленной версии.
- Символ имеет «неопределённую» ширину, и fish считает, что это ширина X, а ваш терминал — Y. В этом случае вам нужно либо изменить конфигурацию терминала, либо установить $fish_ambiguous_width на правильное значение.
- Символ является эмодзи, а система-хост поддерживает только Unicode 8, в то время как вы работаете с терминалом на системе с Unicode >= 9. В этом случае установите $fish_emoji_width в 2.
Это также означает, что некоторые вещи не поддерживаются:
- Шрифты с переменной шириной — у fish нет возможности определить ширину конкретного символа, так как он не влияет на отображение шрифта терминала.
- Различные ширины для нескольких символов с неопределённой шириной — fish не может знать, какую ширину вы назначаете каждому символу.
Удаление fish
Если вы хотите удалить fish, сначала убедитесь, что fish не используется в качестве вашей оболочки. Выполните chsh -s /bin/bash, если вы не уверены.
Если вы установили его с помощью менеджера пакетов, просто используйте функцию удаления этого менеджера. Если вы самостоятельно собрали fish, предполагая, что вы установили его в /usr/local, сделайте следующее:
rm -Rf /usr/local/etc/fish /usr/local/share/fish ~/.config/fish rm /usr/local/share/man/man1/fish*.1 cd /usr/local/bin rm -f fish fish_indent
Где найти дополнительные инструменты для fish?
Сообщество пользователей fish расширяет fish уникальными и полезными способами с помощью скриптов, которые не всегда подходят для включения в пакет fish. Как правило, потому что они решают узкую проблему, которая вряд ли будет интересна широкой аудитории. Вы можете найти эти расширения, включая подсказки, темы и полезные функции, в различных репозиториях сторонних разработчиков. К ним относятся:
Это не исчерпывающий список, и проект fish не имеет мнения о достоинствах перечисленных выше репозиториев или содержащихся в них скриптах.
© 2022 fish-shell developers
Licensed under the GNU General Public License, version 2.
https://fishshell.com/docs/3.5/faq.html