Bash功能根据文件名搜索和cd



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

别名真的很糟糕。你可以做的是在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 的输出,以便它适用于名称中带有任何有趣符号的任何文件)。
  • 然后用printf引用found目录,以便我可以安全地eval定义go函数。
  • 目标目录是在FindGO的执行时间计算的,这样就不会在每次你想go时调用另一个find(我相信这是一个很酷的功能......如果您不这样做,请告诉我我们可以更改它)。这就是eval的原因.这是此脚本中非常重要的部分。实际上,这就是为什么这部分的解释被埋在一个无聊的列表中间。
  • 我相信文件名中的任何有趣符号都是 100% 安全的!
  • 向OP提出的一个快速问题:为什么使用find而不是locate请参阅评论

享受!


编辑。 愚蠢的我,当然,当,例如,mkdir $'n'; touch $'n/lalala' .这是治疗方法:从内部查找中使用 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."
}

编辑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 的输出,因为如果目录名称以换行符结尾,这将惨败)。哇。我喜欢这个!
  • 其余部分与以前基本相同。还是很贴心的。

干杯。

你很接近,你真正需要的只是对你的命令的粗略版本进行转义或引用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.

怎么样:

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/

最新更新