是否有“向上”的发现?

是否有“向上”的发现?

我发现我问过这个问题在错误的 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(我认为当您传递其他参数时它不会很好地发挥作用)的升级版本,因为它是按名称查找文件的特定解决方案。

相关内容