如何在Linux中遍历目录?


Answers:


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

简短说明:

  • find 查找文件(很明显)

  • .是当前目录,cd位于后面/tmp(恕我直言,它比/tmp直接包含在find命令中更为灵活。cd如果要在此文件夹中执行更多操作,则只能更改一个位置,)。

  • -maxdepth 1-mindepth 1确保find仅在当前目录中查找,并且不将.自身包含在结果中

  • -type d 只查找目录

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

等等!


顺便说一句:注意,所有答案也将找到隐藏的文件夹(即,以点开头的文件夹)!如果您不希望这样做,请在printf或exec选项之前添加`-regex'\ ./ [^ \。]。*'`。
Boldewyn

1
有用的-如果您每次击中只需要执行一个命令;-)-只有我要执行几个命令:
Martin

没问题:采用以下解决方案:transnum.blogspot.de/2008/11/…while..done循环中,您可能会发疯。
Boldewyn 2014年

1
对于某些用例,这是一种非常好的方法。find-exec选项可让您为每个文件/目录运行任何命令。
jtpereyda

451

到目前为止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

18
+ find
1-

19
因此for dir in */; do echo $dir; done是在当前目录的目录。
Ehtesh Choudhury

41
如果可以包含解释dir=${dir%*/}和说明,那就太好了echo ${dir##*/}
杰里米S.

11
这是因为变量dir将在末尾包含反斜杠。他只是删除它以使用干净的名字。%将在末尾删除/。##将在开头删除/。这些是处理子字符串的运算符。
sfratini 2015年

8
如果没有匹配项,则将通过触发循环/tmp/*/,明智的做法是包括检查目录是否实际存在。
Jrs42'1

41

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

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

16

使用包含空格的目录

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


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是在同一外壳中进行的,这就是为什么在我的命令中,我们必须使用来返回到当前目录popd


3

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

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

按目录压缩一堆文件

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

这会列出的所有文件directory,而不仅仅是子目录。
dexteritas


2

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

find命令基于Boldewyn 的答案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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.