【问题标题】:How to traverse directories a path consists of in BASH如何遍历路径包含在 BASH 中的目录
【发布时间】:2019-09-30 15:15:33
【问题描述】:

我要编写一个在目录树结构中运行的文件解析器。一旦我找到一个特定的叶目录,我想遍历该路径所包含的所有目录并在其中执行一些操作。

假设路径是:/d1/d2/d3。 现在我想检查/d1、/d1/d2 和/d1/d2/d3 中是否存在文件x,并按此顺序。

当然,也可以这样做:

fields=`find $base_dir -name "leaf_directory" | grep  -o "/" | wc -l`

[[ $fields > 0 ]] || exit 1

for (( i=1; i <= $fields + 1; i++ )) do
    current_dir="`find $base_dir -name "leaf_directory" | cut -d "/" -f $i`"
    source_path="$source_path$current_dir/"

    if [ -f $source_path$file ]; then
        # do sth.
    fi  
done

但是有没有更优雅的解决方案呢?

谢谢。

【问题讨论】:

    标签: bash shell find directory-traversal path-traversal


    【解决方案1】:

    现在我找到了另一种使用内部字段分隔符的解决方案。 / 目录也被考虑在内。

    path="/d1/d2/d3"
    file=x
    
    IFS='/'
    unset current_path
    for current_dir in $path; do
        current_path="${current_path}${current_dir}/"
        if [ -f "${current_path}${file}" ]; then
            printf '%s\n' "$current_path"
        fi  
    done
    unset IFS
    

    【讨论】:

      【解决方案2】:

      请尝试以下方法:

      path="aa/bb/cc"
      file="x"
      
      while true; do
          if [[ -f "$path/$file" ]]; then
              echo "Found: $path/$file"
          fi
          if [[ $path =~ ^/?[^/]+$ ]]; then
              break
          fi
          path="${path%/*}"
      done
      

      问题归结为如何生成上层目录 给定的路径。我上面的代码适用于这两种情况 绝对路径和相对路径。 为了接受以. 或.. 开头的路径,一个小的 需要修改正则表达式。

      [编辑]

      如果您想按aa,aa/bb,..的顺序处理,请尝试 以下:

      path="aa/bb/cc"
      file="x"
      
      while true; do
          array+=("$path")
          if [[ $path =~ ^/?[^/]+$ ]]; then
              break
          fi
          path="${path%/*}"
      done
      for (( i=${#array[@]}-1; i>=0; i-- )); do
          p="${array[$i]}"
          if [[ -f "$p/$file" ]]; then
              echo "Found: $p/$file"
          fi
      done
      

      [编辑]

      如果你想在指定绝对路径时在搜索路径中包含根目录/, 请尝试:

      path="/aa/bb/cc"
      file="x"
      
      while true; do
          array+=("$path")
          if [[ $path =~ ^(/|[^/]+)$ ]]; then
              break
          elif [[ $path =~ ^/[^/]+$ ]]; then
              path="/"
          else
              path="${path%/*}"
          fi
      done
      for (( i=${#array[@]}-1; i>=0; i-- )); do
          p="${array[$i]}"
          if [[ -f "$p/$file" ]]; then
              echo "Found: $p/$file"
          fi
      done
      

      【讨论】:

      • 任何建议如何按上述顺序遍历,即aa,aa/bb,...?
      • 我已根据您的要求更新了我的答案。通过将路径存储在数组中并以相反的顺序处理它们,这是一个简单(不智能)的解决方案。 BR。
      • 现在我在使用/不遍历的绝对路径时遇到了问题。在大多数情况下,这无关紧要,但为了算法的完整性,如果也发生这种情况会很好。 BR。
      • 我已经更新了我的答案,接受了你的提议。我建议您相应地更新您的原始帖子。 BR。
      【解决方案3】:

      这是你想要做的(未经测试)吗?

      fullPath='first/second/third'
      mapfile -t -d '/' dirs <<<"${fullPath}/"
      numDirs=$(( ${#dirs[@]} - 1 ))
      path=''
      file='x'
      for (( dirNr=1; dirNr<=numDirs; dirNr++ )); do
          path="${path}${dirs[$dirNr]}/"
          if [[ -f "${path}${file}" ]]; then
              printf 'Found "%s"\n' "${path}${file}"
          fi
      done
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-31
        • 2011-08-05
        • 2014-09-23
        • 1970-01-01
        • 1970-01-01
        • 2014-10-02
        • 1970-01-01
        相关资源
        最近更新 更多