【发布时间】:2010-10-14 00:20:59
【问题描述】:
你是怎么做到的?我的目录code/,在工作中,被组织在文件夹和子文件夹和子子文件夹中,所有这些(至少在理论上)都包含我想要定期运行的脚本或程序。
【问题讨论】:
你是怎么做到的?我的目录code/,在工作中,被组织在文件夹和子文件夹和子子文件夹中,所有这些(至少在理论上)都包含我想要定期运行的脚本或程序。
【问题讨论】:
类似
my_path=$(find $root -type d | tr '\n' ':')
或
my_path=$(find $root -type d -printf '%p:')
【讨论】:
find "$root" -name ".[a-z]*" -prune -o -type d -printf '%p:' 排除与给定模式匹配的点文件(排除 . 是不明智的,给定的 hack 是避免它的可行 80% 解决方案)。
在 bash 4.0 中,您可以只使用新支持的 ** 运算符。
您必须先在某些设备上启用它:
shopt -s globstar
你可以这样做
echo **
递归回显当前目录的所有后代文件。
请注意,有时它确实倾向于解决过于复杂的目录,因此请在重复出现的最低点使用 **。
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
【讨论】:
\s 是 PCRE 语法;基本 或 扩展 POSIX RE 都不支持它,因此标准 sed 不支持。
echo "hello world" | sed 's/\s/x/' 发出 helloxworld
在你的脚本的最后,加上一行:
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 只检查文件的基本名称,而不是完整路径名。
【讨论】:
我有一个bin 目录$HOME/bin,它会获取我构建的任何程序(或脚本,或程序或脚本的符号链接)的已安装副本。它目前有近 600 个命令(ls | wc -l 说是 604,但由于各种原因有十几个子目录)。
当我测试一个程序时,我会在我构建它的地方执行它;一旦我暂时完成了测试,我会使用我的acquire 脚本acquire 它,它会复制文件并设置其权限。
这给我留下了一个漂亮整洁的配置文件(我不使用.bashrc;我宁愿在登录shell启动时进行一次设置,并且子shell无需解析@987654327即可继承工作环境@ 再次),但是一个相当笨拙的bin 目录。例如,它避免了每次 shell 启动时重置 PATH 的成本,并且考虑到我的路径设置代码有多复杂,这也是一样的!
【讨论】:
以下内容是正确的,包括修剪隐藏目录及其子目录以及正确处理带有换行符或其他空格的名称:
export PATH="${PATH}$(find ~/code -name '.*' -prune -o -type d -printf ':%p')"
我使用类似的技巧来自动设置CLASSPATHs。
【讨论】:
类似这样的:
_path="$(
find <path> -name '.*' -prune -o -type d -print
)"
[[ $_path ]] && _path="${_path//$'\n'/:}" PATH="$PATH:${_path%:}"
如果你有 GNU find 你可以直接使用-printf ':%p'。
【讨论】:
如果您真的需要走这条路,您可以尝试将 PATH 列表最小化一些:删除不包含可执行文件的文件夹。当然,代价是更多的统计数据。 ;-/
PATH=$PATH$(find ~/code -name '.*' -prune -o -type f -a -perm /u+x -printf ':%h\n' | sort | uniq | tr -d '\n')
我会避免在每个 shell 生成时都这样做。应该使用某种缓存。例如,将此行添加到您的 ~/.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/:$//'
【讨论】:
我也一直在寻找解决这个问题的方法。如果 bash 有办法说对于某些路径,您希望它递归地搜索文件,那就太好了。例如
PATH="$PATH:/usr/local/bin:~/bin**"
~/bin 将搜索该目录及其所有子目录,而不会弄乱您的 PATH 变量。
由于没有实现,我的临时解决方案是将所有内容放在我的 bin 目录中,然后创建另一个目录“bindir”,其中包含指向“bin”中实际可执行文件的符号链接,但它们整齐地排列在子目录中以使它们更容易去寻找。
我唯一的问题是我是否应该使用硬链接而不是符号链接。
【讨论】:
试试这个方法:export PATH="$PATH:$(du "~/code/" | cut -f2 | tr '\n' ':' | sed 's/:*$//')"
这会将 ~/code 本身及其所有子目录添加到 $PATH
说明:
- du 将每行显示所有子目录信息
- cut -f2 将提取第二列,即子目录的名称
- tr '\n' ':' 会将每个链接中断更改为冒号。这会将所有行合并为一行,并且子目录由冒号分隔
- sed 's/:*$//' 将删除最后一个冒号
【讨论】: