如何以递归方式将子目录添加到PATH?

时间:2009-03-18 05:53:30

标签: bash file path

你是怎么做到的?我的目录code/在工作中被组织在文件夹,子文件夹和子文件夹中,所有这些(至少在理论上)都包含我想要定期运行的脚本或程序。

9 个答案:

答案 0 :(得分:22)

在您的脚本结束时,输入以下行:

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仅检查文件的基本名称,而不是完整路径名。

答案 1 :(得分:18)

以下是正确的事情,包括修剪隐藏目录及其子项以及使用换行符或其他空格正确处理名称:

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

我使用类似的技巧来自动设置CLASSPATH s。

答案 2 :(得分:2)

这样的东西
my_path=$(find $root -type d | tr '\n' ':')

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

答案 3 :(得分:2)

如果你真的需要沿着这条路走下去,你可以尝试最小化PATH列表更多:删除不包含可执行文件的文件夹。当然,代价是更多的统计数据。 ; - /

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

我会避免在每个shell spawn中执行此操作。应该使用某种缓存。例如,将此行添加到〜/ .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/:$//'

答案 4 :(得分:1)

在bash 4.0中,您可以使用新支持的**运算符。

您必须首先在某些地方启用它:

shopt -s globstar

然后你可以做

echo ** 

以递归方式回显所有当前目录的后代文件。

请注意,有时候它确实倾向于过度复杂的dirs,所以在最低的重复点使用**。

echo **/  

巧合的是,递归地发出所有目录名,只发出目录名。 (不包括当前的目录)

echo ./**/ 

包括当前目录。 (顺便说一下,它也会跳过隐藏的目录)

因此,这应该适合于创建路径字符串:

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

如果你不想要相对路径,

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

确认

根据你对其他帖子的评论,听起来你想要的行为就像'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  

答案 5 :(得分:1)

我一直在寻找这个问题的解决方案。如果bash有办法说某些路径,你希望它以递归方式搜索文件,那就太好了。例如

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

其中~/bin将搜索该目录及其所有子目录,而不会弄乱PATH变量。

由于没有实现,我的临时解决方案是将所有内容放在我的bin目录中,然后创建另一个目录“bindir”,其中包含指向“bin”中实际可执行文件的符号链接,但是它们整齐地排列到子目录中以使它们更容易找到。

我唯一的问题是我是否应该使用硬链接而不是符号链接。

答案 6 :(得分:0)

我有一个bin目录$HOME/bin,它可以获得我构建的任何程序的安装副本(或脚本,或程序或脚本的符号链接)。它目前有近600个命令(ls | wc -l表示604,但由于各种原因,有十几个子目录。)

当我测试程序时,我会在构建它的地方执行它;一旦我暂时完成了测试,我acquire使用我的acquire脚本复制文件并设置权限。

这给我留下了一个漂亮整洁的配置文件(我不使用.bashrc;我宁愿在登录shell启动时进行一次设置,子shell继承工作环境而不必解析再次.bashrc,但是一个相当笨拙的bin目录。例如,它避免了每次shell启动时重置PATH的成本,并且考虑到我的路径设置代码的复杂程度,也是如此!

答案 7 :(得分:0)

这样的事情:

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

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

如果你有GNU查找,你可以直接使用-printf ':%p'

答案 8 :(得分:0)

尝试这种方式:
export PATH="$PATH:$(du "~/code/" | cut -f2 | tr '\n' ':' | sed 's/:*$//')"
这会将〜/ code本身及其所有子目录添加到$ PATH
说明:
-du将在每行显示所有子目录信息
-cut -f2将提取第二列,即子目录的名称
-tr '\n' ':'会将每个链接中断更改为冒号。这会将所有行合并为一行,并且子目录由冒号分隔
-sed 's/:*$//'将删除最后一个冒号