Bash函数根据文件名进行搜索和cd

时间:2013-10-29 21:09:27

标签: bash

我正在尝试将bash函数放在.bashrc中。

这与我的想法一致......

FindGO () 
{
alias go=cd $(find -name $1 | egrep -o ".+\/"); #finds file and chops of name at end for cd to work
echo "file directory containing $1 now aliased to go"; 
}

我希望能帮助您实现这一目标(如果找不到文件,请输入错误消息)。

更新 我将保留当时的帮助。但如果有人想要真正做到这一点,请考虑FZF

3 个答案:

答案 0 :(得分:1)

别名真的很糟糕。您可以做的是在FindGO函数中定义一个函数。这听起来很酷:

FindGO () {
    local qfound
    local found=$(find -name "$1" -printf '%h' -quit)
    if [[ -z $found ]]; then
        echo "Oh dear, I couldn't find \`$1' anywhere... and I really looked everywhere."
        return 1
    fi
    printf -v qfound '%q' "$found"
    eval "go() { cd \"$(pwd)\"/$qfound; }"
    echo "Will change directory to the one containing \`$1' (namely \`$found') with the function go."
}

我知道,eval是邪恶的,但它与安全引用的$qfound变量一起使用。

  • find-printf '%h'一起使用,只会输出文件的目录部分(以免grep变得无用)。
  • 使用-quit开关,以便find在第一个找到的文件后立即退出。这会加快速度!如果你想在有多个找到的文件时想要一些特殊的东西,你可以调整它(但要注意你将如何获得find的输出,以便它可以与任何名字中带有任何有趣符号的文件一起使用)。
  • 然后使用found引用printf目录,以便我可以安全地eval定义go功能。
  • 目标目录是在FindGO的执行时间计算出来的,这样每次你想find时都不会调用另一个go(我相信这是一个很酷的功能......如果你不这样做,请告诉我们我们可以改变它。这就是eval的原因。这是这个剧本中非常重要的一部分。实际上,这就是为什么这部分的解释被埋没在无聊的清单中间。
  • 我认为文件名中任何有趣的符号都是100%安全的!
  • OP的一个简单问题:为什么使用find而不是locate 看到评论

享受!


编辑。愚蠢的我当然在例如mkdir $'\n'; touch $'\n/lalala'时失败了。这是治愈方法:在find中使用bash的printf '%q'

FindGO () {
    local qfound=$(find -name "$1" -exec bash -c 'printf "%q" "$1"' _ {} \; -quit)
    if [[ -z $qfound ]]; then
        echo "Oh dear, I couldn't find \`$1' anywhere... and I really looked everywhere."
        return 1
    fi
    eval "go() { cd \"$(pwd)\"/$qfound; }"
    echo "Will change directory to the one containing \`$1' (namely \`$qfound') with the function go."
}

Edit2。我发誓,写下前两个版本的人非常愚蠢。因为这是 解决方案。如果你读到(并理解)到这里,你可能已经学到了一些有趣的东西。这里有更多:

FindGO () {
    local qfound=$(find -name "$1" -execdir bash -c 'printf "%q" "$PWD"' {} \; -quit);
    if [[ -z $qfound ]]; then
        echo "Oh dear, I couldn't find \`$1' anywhere... and I really looked everywhere.";
        return 1;
    fi;
    eval "go() { cd $qfound; }";
    echo "Will change directory to the one containing \`$1' (namely \`$qfound') with the function go.";
}

正如你所看到的,解决方案是绝对明显的,理智的,明确的,没有错综复杂的,优雅的。因为它应该始终是:

  • find-execdir标记一起使用,并请求bash很好地printf '%q'$PWD(注意:我要求变量 $PWD,而不是命令pwd的输出,因为如果目录名以换行符结尾,这将失败。)哇。我喜欢这个!
  • 其余部分与以前大致相同。还是很甜蜜。

干杯。

答案 1 :(得分:0)

怎么样:

findGO()
{
  TMP=$PWD
  PLACE=$(find . -iname $1 | egrep -o ".+\/")
  alias go="cd $TMP/${PLACE:2:${#PLACE}}"
  cd $PLACE
  echo "$TMP/${PLACE:2:${#PLACE}} now aliased to go"
}

这也可能有所帮助: http://www.tecmint.com/35-practical-examples-of-linux-find-command/

答案 2 :(得分:0)

你很亲密,你真正需要的只是你的命令的粗略版本是逃避或引用cd$(...之间的空格。这是一个更加文件名安全的版本:

foo () 
{ 
    alias go="cd '$(dirname "$(find . -name "$1" -print -quit)")'"
    echo "file directory containing $1 now aliased to go"
}

内心的一些解释:

[1] find . -name "$1" -print -quit
# Find the first file named by the argument, print it 
# and quit so we don't get too many files.

[2] dirname "$([1])"
# Execute the aforementioned command, capture its output, and 
# pass it as the argument to `dirname`. 
# `dirname` simply cuts off the end of the string from the 
# last / it finds through the end.

alias go="cd '$([2])'"
# Alias `go` to cd to the output of the previous command
# (directory containing first file found). 
# Put in quotes in case there are any funny characters. 
# Will break if there is a single quote in the name, but that can't be helped in bash.