1

我正在尝试制作一个 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

4

3 回答 3

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变量一起使用。

  • 使用findwith-printf '%h'只会输出文件的目录部分(这样你grep就变得没用了)。
  • 使用-quit开关,以便find在找到第一个文件后立即退出。这将大大加快速度!如果您希望在找到多个文件时发生一些特殊的事情,您可以对此进行调整(但请注意您将如何获得find' 的输出,以便它适用于名称中包含任何有趣符号的任何文件)。
  • 然后引用found目录,printf以便我可以安全eval地定义go函数。
  • 目标目录是在FindGO's 执行时计算的,以免find每次你想调用另一个go(我相信这是一个很酷的功能......如果你不这样做,让我知道我们可以改变它)。这就是eval. 这是这个脚本的一个非常重要的部分。实际上这就是为什么这部分的解释被埋在一个无聊的列表中间的原因。
  • 我相信文件名中的任何有趣符号都是 100% 安全的!
  • 对 OP 的一个快速问题:为什么使用find而不是locate 见评论

享受!


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

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."
}

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

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,因为如果目录名称以换行符结尾,这将失败)。哇。我喜欢这个!
  • 其余部分与之前大体相同。还是很甜的。

干杯。

于 2013-10-29T22:16:53.117 回答
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/

于 2013-10-29T21:26:07.740 回答
0

您已经很接近了,对于粗略版本的命令,您真正需要的只是转义或引用 and 之间的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.
于 2013-10-29T21:27:10.187 回答