Подтвердить что ты не робот

Bash: рекурсивно добавление подкаталогов в путь

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

Его превращение моего иначе живописного .bashrc в бельмо!

Спасибо!

4b9b3361

Ответ 1

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

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 проверяет только базовое имя файла, а не полное имя пути.

Ответ 2

Ниже перечислены "Правильные вещи", включая обрезку скрытых каталогов и их детей и правильное обращение с именами с символами перевода строки или другими пробелами:

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

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

Ответ 3

Что-то вроде

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

или

my_path=$(find $root -type d -printf '%p:')

Ответ 4

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

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

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

EDIT: здесь переписывается без вашего отсутствующего -printf

find ~/code -name '.*' -prune -o -type f -a -perm /u+x -print | sed '[email protected]/[^/]\[email protected]:@' | sort | uniq | tr -d '\n' | sed 's/^/:/; s/:$//'

Ответ 5

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

Вы должны сначала включить его с помощью:

shopt -s globstar

Затем вы можете сделать

echo ** 

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

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

echo **/  

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

echo ./**/ 

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

Это должно быть соответствующим образом для создания строки пути:

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

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

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

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  

Ответ 6

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

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

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

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

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

Ответ 7

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

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

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

Ответ 8

Что-то вроде этого:

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

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

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