别名真的很烂。你可以做的是在你的函数中定义一个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
with-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
,因为如果目录名称以换行符结尾,这将失败)。哇。我喜欢这个!
- 其余部分与之前大体相同。还是很甜的。
干杯。