Тильда в PATH может указывать не на ваш HOME

Don't Put Tilde In Your Path

Тильда в PATH может указывать не на ваш HOME

В bash и zsh тильда раскрывается в домашний каталог только в неприкавыченных строках или сразу после = и : в присваиваниях. Если написать export PATH="$PATH:~/.local/bin/", то в PATH попадёт буквальная тильда, и оболочка будет искать программы в подкаталоге ./~/.local/bin/ относительно текущей директории. Автор показывает, как это приводит к запуску подставного бинарника, и советует заменить ~ на $HOME.

Bash проверяет каждое присваивание переменной на неприкавыченные тильда-префиксы сразу после ‘:’ или первого ‘=’, и выполняет раскрытие тильды в этих случаях.
  1. SoftTalker

    Я никогда не использую тильду в скриптах, только для удобства при вводе команд в интерактивном режиме.

    В остальных случаях $HOME, у которого тоже есть свои подводные камни, но они такие же, как у любой другой переменной окружения.

  2. amarshall

    Или можно просто… не брать тильду в кавычки. Люди, кажется, всегда рефлекторно берут в кавычки «строки» в Bash, не осознавая, что (почти) всё является строкой, а большинство строк не заключается в кавычки, и это было бы странно (например, никто не пишет `"ls" "-a" "foo"`).

  3. thefilmore

    Можно просто сделать:

    PATH=~/.local/bin:$PATH

    PATH уже экспортирована. Кавычки для присваиваний тоже не нужны.

  4. FeepingCreature

    Вроде бы ты должен был заметить это по тому, что твой ~/.local/bin в PATH не работает?

  5. alexpotato

    Не обязательно про тильды, но про некоторые безумства, которые могут происходить с bash в крупных организациях:

    На прошлой работе я пытался выяснить, какая часть моего bashrc устанавливает конкретную переменную окружения. Я предположил, что это какая-то настройка по умолчанию в моём пользовательском профиле и/или наследуется из /etc/<что-то>.

    Я довольно быстро понял, что мой bashrc импортирует какие-то другие файлы. Опять же, предполагалось, что это будет один файл на уровне импорта.

    Оказалось, что там было 10+ уровней импорта, начиная с «ur-bashrc», а затем слой за слоем всё больше и больше импортов, чтобы в итоге добраться до профиля пользовательского уровня.

    Это было настолько запутанно, что я сходил с ума, пока не нашёл этот пост на Stack Exchange: https://unix.stackexchange.com/questions/813/how-to-determin...

    Он включает «трассировку» для импортов bash, чтобы затем можно было сузить круг поиска того, где устанавливается переменная окружения.

  6. dspillett

    Я собирался сказать «у меня это всегда вроде бы работает», а потом увидел «… на самом деле работает в Bash и Zsh, потому что …».

    Ещё один bash-изм, который мне нужно осторожно не использовать, когда я пытаюсь быть переносимым.

    Стоит отметить, что во многих системах /bin/sh — это не bash (и не zsh), так что если вы хотите полагаться на bash-измы (или просто не хотите утруждать себя их поиском), будьте конкретны и используйте «#!/bin/bash» в качестве шебанга. В Debian и подобных системах это обычно dash, например.

  7. the__alchemist

    Хотелось бы, чтобы дистрибутивы Linux поставляли программу «Терминал»/«CLI» и т.п., отделённую от скриптового языка. Имели универсальную переменную окружения Path, не привязанную к конкретной оболочке. Позволяли выполнять команды cd, запускать python/git/cargo/произвольные приложения и т.д., и имели хорошую систему закладок и автодополнения. Кажется, что смешение скриптового языка и CLI-приложения — корень этих сложностей и тонкостей.

    Если вы используете shell-скриптинг (и предпочитаете Bash и т.п. вместо Python), вы бы продолжали использовать Bash/Fish/Zsh и т.д. Если вы используете CLI для запуска приложений без GUI, навигации по каталогам и выполнения операций с файловой системой, то вы бы использовали простой терминал.

  8. ligarota

    Просто создайте файл ~, который является симлинком на домашний каталог :)

    Вот это уровень большого мозга

Ещё за этот день

2026-10-11