Как рекурсивно добавить подкаталоги в PATH? - PullRequest
19 голосов
/ 18 марта 2009

Как ты это делаешь? Моя директория code/ на работе организована в папки, подпапки и подпапки, каждая из которых (по крайней мере теоретически) содержит скрипты или программы, которые я хочу запускать на регулярной основе.

Ответы [ 8 ]

22 голосов
/ 18 марта 2009

В конце вашего скрипта поставьте строку:

PATH=${PATH}:$(find ~/code -type d | tr '\n' ':' | sed 's/:$//')

Это добавит каждый каталог в вашем дереве ~ / code к текущему пути. Сама идея мне не нравится, я предпочитаю, чтобы только несколько каталогов содержали мои собственные исполняемые файлы и явно перечисляли их, но для каждого свои.

Если вы хотите исключить все скрытые каталоги, вам, по сути, нужно удалить каждую строку, имеющую последовательность "/." (чтобы не проверять подкаталоги и в скрытых каталогах):

PATH=${PATH}:$(find ~/code -type d | sed '/\/\\./d' | tr '\n' ':' | sed 's/:$//')

Это остановит вас от получения каталогов, таких как ~/code/level1/.hidden/level3/ (то есть, он остановит поиск в поддеревьях, как только обнаружит, что они скрыты). Если вы хотите только сохранить скрытые каталоги, но при этом разрешить скрытые каталоги под ними, используйте:

PATH=${PATH}:$(find ~/code -type d -name '[^\.]*' | tr '\n' ':' | sed 's/:$//')

Это позволило бы ~/code/level1/.hidden2/level3/, но запретить ~/code/level1/.hidden2/.hidden3/, поскольку -name проверяет только базовое имя файла, а не полный путь.

18 голосов
/ 18 марта 2009

Следующее делает правильно, включая обрезку скрытых каталогов и их дочерних элементов и правильную обработку имен с помощью новых строк или других пробелов:

export PATH="${PATH}$(find ~/code -name '.*' -prune -o -type d -printf ':%p')"

Я использую аналогичный трюк для автоматической установки CLASSPATH с.

2 голосов
/ 20 марта 2009

Если вам действительно нужно пойти по этому пути, вы можете попытаться свести к минимуму этот список PATH: отбросьте папки, не содержащие исполняемых файлов. Конечно, за счет еще большей статистики. - /

PATH=$PATH$(find ~/code -name '.*' -prune -o -type f -a -perm /u+x -printf ':%h\n' | sort | uniq | tr -d '\n')

Я бы избегал делать это при каждом появлении снарядов. Какой-то вид кэширования должен быть использован. Например, добавьте эту строку в ваш ~ / .bashrc:

[ -s ~/.codepath ] && export PATH=$PATH$(<~/.codepath)

и запустить

find ~/code -name '.*' -prune -o -type f -a -perm /u+x -printf ':%h\n' |sort |uniq |tr -d '\n' > ~/.codepath

только когда вы знаете, что что-то действительно изменилось.

РЕДАКТИРОВАТЬ: вот переписать без пропущенного -printf

find ~/code -name '.*' -prune -o -type f -a -perm /u+x -print | sed 's@/[^/]\+$@:@' | sort | uniq | tr -d '\n' | sed 's/^/:/; s/:$//'
2 голосов
/ 18 марта 2009

Что-то вроде

my_path=$(find $root -type d | tr '\n' ':')

или

my_path=$(find $root -type d -printf '%p:')
1 голос
/ 18 января 2012

Я тоже искал решение этой проблемы. Было бы здорово, если бы у bash был способ сказать, что для определенных путей вы хотите, чтобы он искал файлы рекурсивно. Например

PATH="$PATH:/usr/local/bin:~/bin**"

где ~/bin будет искать этот каталог и все его подкаталоги, не внося путаницы в вашу переменную PATH.

Поскольку это не реализовано, мое временное решение состоит в том, чтобы поместить все в мой каталог bin, а затем создать еще один каталог "bindir", который содержит символические ссылки на фактические исполняемые файлы в "bin", но они аккуратно расположены в подкаталогах, чтобы сделать их проще найти.

Мой единственный вопрос, стоит ли мне использовать жесткие ссылки вместо символических ссылок.

1 голос
/ 18 марта 2009

В bash 4.0 вы можете просто использовать недавно поддерживаемый оператор **.

Сначала нужно включить его в некоторых случаях:

shopt -s globstar

Вы можете сделать

echo ** 

, который рекурсивно выводит все файлы, которые являются потомками текущего каталога.

Остерегайтесь, что иногда он может спастись на слишком сложных режиссерах, поэтому используйте ** в самой низкой точке повторения.

echo **/  

По совпадению, выдает рекурсивно все имена каталогов и только имена каталогов. (Исключая текущий каталог)

echo ./**/ 

Включает текущий каталог. (Кстати, он также пропускает скрытые каталоги)

Таким образом, это должно подходить для создания строки пути:

echo ./**/ | sed 's/\s\s*/:/g'

А если вам не нужны относительные пути,

echo $PWD/**/ | sed 's/\s\s*/:/g' 

1026 * Ack * Из вашего комментария к одному из других постов кажется, что вам нужно поведение, похожее на «Ack». Если вы намеревались использовать комбинацию find + grep, этот инструмент, как правило, намного эффективнее и проще в использовании для этой задачи. извед Пример: # search for 'mystring' in all c++ files recursively ( excluding SCM dirs and backup files ) ack "mystring" --type=cpp # finds all text files not in an SCM dir ( recursively) and not a backup using type heuristics. ack -f --type=text

0 голосов
/ 18 марта 2009

Примерно так:

_path="$(
  find <path> -name '.*' -prune -o -type d -print
  )" 

[[ $_path ]] && _path="${_path//$'\n'/:}" PATH="$PATH:${_path%:}"   

Если у вас есть GNU, вы можете использовать -printf ':%p' напрямую.

0 голосов
/ 18 марта 2009

У меня есть один каталог bin $HOME/bin, который получает установленную копию любых создаваемых мной программ (или сценариев, или символических ссылок на программы или сценарии). В настоящее время в нем содержится почти 600 команд (ls | wc -l говорит 604, но по разным причинам существует около десятка подкаталогов).

Когда я тестирую программу, я выполняю ее там, где я ее строю; После того, как я пока что проверил тестирование, я acquire запустил его со своим acquire скриптом, который копирует файл и устанавливает для него права доступа.

Это оставляет мне хороший аккуратный профиль (я не использую .bashrc; я бы предпочел выполнить настройку один раз, когда запускается оболочка входа в систему, а подоболочки наследуют рабочую среду без разбора .bashrc снова), но довольно неловкий каталог bin. Это позволяет избежать затрат на сброс PATH при каждом запуске оболочки, например, и учитывая, насколько сложен мой код установки пути, это также хорошо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...