我发现我问过这个问题在错误的 stackexchange 网站上。
要查找从某个路径开始的文件,我可以使用find <path> ...
。如果我想“向上”查找,即在父目录中,以及它的父目录中,并且......,是否有等效的工具?
用例是知道在例如包括上游某处的一些常见 makefile 函数的 makefile 中使用的正确点数(../../x.txt 或 ../../../x.txt?)。
文件夹结构的预期用途如下:
/
/abc
/abc/dce/efg/ghi
/abc/dce/efg2
$ cd /abc/dce/efg/ghi
$ touch ../../x.txt
$ upfind . -name X*
../../x.txt
$ upfind . -name Y* || echo "not found"
not found
$ touch /abc/dce/efg2/x.txt
$ upfind . -name Y* || echo "not found"
not found
$
简而言之:
- 它应该搜索这个文件夹、它的父文件夹、它的父文件夹的父文件夹......
- 但不在其兄弟节点中(如 'find' 所示)
- 它应该报告相对于当前路径找到的文件
答案1
现有答案不够充分(详情如下)。
upfind
将其放入您的 中某处命名的脚本中$PATH
,然后chmod +x /the/path/upfind
:
#!/usr/bin/env bash
DIR=$(readlink -f "$1")
# Alternative: use current working dir; but then also replace ${@:2} with $@ on line 8
# and $1 with $PWD when calling realpath
# DIR=$PWD
while
RESULT=$(find "$DIR"/ -maxdepth 1 "${@:2}")
# echo "Debugging upfind - search in $DIR gives: $RESULT"
[[ -z $RESULT ]] && [[ "$DIR" != "/" ]]
do DIR=$(dirname "$DIR"); done
realpath --relative-to="$1" "$RESULT"
# Alternative: output absolute path
# echo "$RESULT"
您可能考虑的两种替代方案可以在脚本中切换;使用 $PWD 而不是第一个参数意味着我们需要传递 $@(所有参数)来查找,并通过注释 realpath 行并仅回显 $RESULT 来输出完整路径而不是相对路径。
注意使用 do-while 循环来自这个答案。
Choroba 和 Matthew Wolff 弄错了结束条件;因此他们无法找到实际上位于文件系统根目录中的文件。他们还都执行了 cd,而这并不是我希望 bash 脚本执行的操作。Peter O 的解决方案看起来更好,但对于我构建的测试用例,它什么也没有输出,而且编写新的 bash 脚本比调试现有脚本更容易。
答案2
您可以使用这个简单的脚本。它会向上遍历目录树并搜索指定的文件。
#! /bin/bash
prev=.
while [[ $PWD != "$prev" ]] ; do
find "$PWD" -maxdepth 1 "$@"
prev=$PWD
cd ..
done
用法:
upfind -name 'x*'
答案3
您只需将路径拆分为其组成目录节点,然后谨慎地搜索每个节点即可。这是一个bash
脚本。
IFS=/; dn=($1); ct=${#dn[@]}
for((i=0; i<ct; i++)); do
subd+=/"${dn[i]}"
dots=$(for((j=ct-i; j>1; j--)); do printf "../"; done)
find "$subd" -maxdepth 1 -type f -name "$2" -printf "$dots%f\n"
done
运行... 将upfind $HOME/zt" "Y*"
产生以下输出
雅巴存在于/,/主页/用户, /主页/用户/zt
../../../YABBA
../YABBA
YABBA
答案4
使用我自己的解决方案扩展@choroba 的答案来查找文件的向上位置(按名称):
upfind() {
ORIG_DIR="$PWD"
while [[ "$PWD" != / ]] ; do
if find "$PWD"/ -maxdepth 1 -type f -name "$@" | grep -q "$@"; then
echo "$PWD" && builtin cd "$ORIG_DIR"
return 0
else
builtin cd ..
fi
done
builtin cd "$ORIG_DIR"
return 1
}
例子:
> upfind packageInfo
/home/matthew/development/packageRoot
它将返回错误代码,如果您在条件中使用它,这将非常有用。但是,此解决方案不是find
(我认为当您传递其他参数时它不会很好地发挥作用)的升级版本,因为它是按名称查找文件的特定解决方案。