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