【问题标题】:How to loop over directories in Linux?如何在 Linux 中遍历目录?
【发布时间】:2011-01-07 15:42:07
【问题描述】:

我正在 Linux 上用 bash 编写脚本,需要遍历给定目录中的所有子目录名称。如何遍历这些目录(并跳过常规文件)?

例如:
给定目录是/tmp/
它有以下子目录:/tmp/A, /tmp/B, /tmp/C

我想检索 A、B、C。

【问题讨论】:

标签: linux bash


【解决方案1】:

到目前为止,所有答案都使用find,所以这里只有一个外壳。在您的情况下不需要外部工具:

for dir in /tmp/*/     # list directories in the form "/tmp/dirname/"
do
    dir=${dir%*/}      # remove the trailing "/"
    echo "${dir##*/}"    # print everything after the final "/"
done

【讨论】:

  • +1 - 当您可以在通配符上附加斜杠时,为什么还要使用find
  • so for dir in */; do echo $dir; done 用于当前目录中的目录。
  • 如果它可以包含 dir=${dir%*/}echo ${dir##*/} 正在做什么的解释,那就太好了。
  • 这是因为变量 dir 会在末尾包含反斜杠。他只是为了有一个干净的名字而删除它。 % 将删除最后的 / 。 ## 将删除开头的 /。这些是处理子字符串的运算符。
  • 如果没有匹配,循环将被/tmp/*/触发,明智的做法是检查目录是否真的存在。
【解决方案2】:
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'

简短说明:

  • find 查找文件(很明显)

  • . 是当前目录,在cd 之后是/tmp (恕我直言,这比在find 命令中直接使用/tmp 更灵活。你只有一个地方,即cd,如果您想在此文件夹中执行更多操作,请更改)

  • -maxdepth 1-mindepth 1 确保 find 只在当前目录中查找,而不在结果中包含 . 本身

  • -type d 仅查找目录

  • -printf '%f\n 仅打印每次点击找到的文件夹的名称(加上换行符)。

等等!

【讨论】:

  • 顺便说一句:请注意,所有答案也会找到隐藏文件夹(即以点开头的文件夹)!如果您不希望这样,请在 printf 或 exec 选项之前添加 `-regex '\./[^\.].*'`。
  • 很有帮助——如果你只需要为每次点击执行一个命令;-)——只有我有几个命令要执行:-(.
  • 没问题:调整这个解决方案:transnum.blogspot.de/2008/11/…while..done 循环内你会发疯的。
  • 这对于某些用例来说是一个非常好的方法; find-exec 选项允许您为每个文件/目录运行任何命令。
【解决方案3】:

您可以使用以下命令遍历所有目录,包括隐藏目录(以点开头):

for file in */ .*/ ; do echo "$file is a directory"; done

注意:仅当文件夹中至少存在一个隐藏目录时,使用列表*/ .*/ 在 zsh 中才有效。在 bash 中,它还会显示 ...


bash 包含隐藏目录的另一种可能性是使用:

shopt -s dotglob;
for file in */ ; do echo "$file is a directory"; done

如果你想排除符号链接:

for file in */ ; do 
  if [[ -d "$file" && ! -L "$file" ]]; then
    echo "$file is a directory"; 
  fi; 
done

要在每个解决方案中仅输出尾随目录名称(A、B、C),请在循环中使用:

file="${file%/}"     # strip trailing slash
file="${file##*/}"   # strip path and leading slash
echo "$file is the directoryname without slashes"

示例(这也适用于包含空格的目录):

mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces"
for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done

【讨论】:

    【解决方案4】:

    适用于包含空格的目录

    灵感来自Sorpigal

    while IFS= read -d $'\0' -r file ; do 
        echo $file; ls $file ; 
    done < <(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d -print0)
    

    原始帖子(不适用于空格)

    灵感来自Boldewyn:带有find 命令的循环示例。

    for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do
        echo $D ;
    done
    

    【讨论】:

      【解决方案5】:
      find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"
      

      【讨论】:

      • 这也很好,无需basename。我更喜欢这个而不是我的答案。
      【解决方案6】:

      我最常使用的技术是find | xargs。例如,如果你想让这个目录中的每个文件及其所有子目录都可读,你可以这样做:

      find . -type f -print0 | xargs -0 chmod go+r
      find . -type d -print0 | xargs -0 chmod go+rx
      

      -print0 选项以 NULL 字符而不是空格结尾。 -0 选项以相同的方式拆分其输入。所以这是在带有空格的文件上使用的组合。

      您可以将这条命令链想象为获取find 输出的每一行并将其粘贴在chmod 命令的末尾。

      如果您想将命令作为其参数运行在中间而不是最后,您必须有点创意。例如,我需要切换到每个子目录并运行命令latemk -c。所以我使用了(来自Wikipedia):

      find . -type d -depth 1 -print0 | \
          xargs -0 sh -c 'for dir; do pushd "$dir" && latexmk -c && popd; done' fnord
      

      这具有for dir $(subdirs); do stuff; done 的效果,但对于名称中有空格的目录是安全的。此外,对stuff 的单独调用是在同一个shell 中进行的,这就是为什么在我的命令中我们必须使用popd 返回到当前目录的原因。

      【讨论】:

        【解决方案7】:

        您可以构建的最小 bash 循环(基于 ghostdog74 答案)

        for dir in directory/*                                                     
        do                                                                                 
          echo ${dir}                                                                  
        done
        

        按目录压缩一大堆文件

        for dir in directory/*
        do
          zip -r ${dir##*/} ${dir}
        done                                               
        

        【讨论】:

        • 这会列出directory的所有文件,而不仅仅是子目录。
        【解决方案8】:

        如果你想在一个for循环中执行多个命令,你可以将findmapfile(bash >= 4)的结果保存为一个变量,然后用${dirlist[@]}遍历数组。它也适用于包含空格的目录。

        find 命令基于 Boldewyn 的 answer。有关find 命令的更多信息可以在此处找到。

        IFS=""
        mapfile -t dirlist < <( find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n' )
        for dir in ${dirlist[@]}; do
            echo ">${dir}<"
            # more commands can go here ...
        done
        

        【讨论】:

          【解决方案9】:

          find . -type d -maxdepth 1

          【讨论】:

          • 这个答案很好,除了我收到完整路径,而我只想要目录的名称。
          猜你喜欢
          • 1970-01-01
          • 2010-12-16
          • 1970-01-01
          • 2023-03-31
          • 2011-07-23
          • 2018-01-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多