如何在Linux中循环目录?

时间:2010-01-21 08:57:22

标签: linux bash

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

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

我想要检索A,B,C。

9 个答案:

答案 0 :(得分:385)

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

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 :(得分:116)

cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'

一个简短的解释:find找到文件(很明显)

  • 。是当前目录,在cd之后它是/tmp(恕我直言,这比直接在查找命令中/tmp更灵活。你只有一个地方,cd,要改变,如果您希望在此文件夹中执行更多操作)

  • -maxdepth 1-mindepth 1确保find确实只查看当前目录,并且结果中不包含“.” / p>

  • -type d仅查找目录

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

瞧瞧!

答案 2 :(得分:38)

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

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

答案 3 :(得分:14)

使用包含空格的目录

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

答案 4 :(得分:7)

find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"

答案 5 :(得分:5)

我最常使用的技术是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的当前目录。

答案 6 :(得分:2)

find . -type d -maxdepth 1

答案 7 :(得分:2)

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

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

按目录

压缩一大堆文件
for dir in directory/*
do
  zip -r ${dir##*/} ${dir}
done                                               

答案 8 :(得分:0)

如果要在for循环中执行多个命令,则可以将find的结果与mapfile(bash> = 4)保存为变量,并使用{{1 }}。它也可以用于包含空格的目录。

${dirlist[@]}命令基于Boldewyn的answer。可以在此处找到有关find命令的更多信息。

find