我有一个文件夹,其中包含一些目录和一些文件(有些文件是隐藏的,以点开头)。

for d in *; do
 echo $d
done


将循环浏览所有文件,但是我只想循环浏览目录。我该怎么办?

#1 楼

您可以在末尾指定一个斜杠以仅匹配目录:

for d in */ ; do
    echo "$d"
done


评论


请注意,它还包括指向目录的符号链接。

–StéphaneChazelas
13年8月14日在16:09

那么您如何排除符号链接?

–rubo77
13年8月14日在22:55

@ rubo77:您可以使用[[-L $ d]]测试$ d是否是符号链接。

–乔罗巴
13年8月14日在23:00

@choroba:在这种情况下,[[-L“ $ f”]]不会排除符号链接,您必须使用[[-L“ $ {f%/}”]]去除斜杠(请参见测试与斜杠链接)

–rubo77
13-10-23在6:54



@timbram:*是通配符,表示“任何”。 /表示“任何内容”必须是目录才能匹配通配符表达式。 ;是for循环的一部分,它将do与for分开。

–乔罗巴
17年7月28日在16:11

#2 楼

您可以使用-d进行测试:

 for f in *; do
    if [ -d "$f" ]; then
        # $f is a directory
    fi
done
 


这是文件测试运算符之一。 br />

评论


请注意,它将包括指向目录的符号链接。

–StéphaneChazelas
13年8月14日在16:12

如果[[-d“ $ f” &&! -L“ $ f”]]将排除符号链接

–rubo77
13-10-22在6:33



将在空目录上中断。如果[[“ $ f” =“ *”]];然后继续;科幻

– Piskvor离开了建筑物
19年4月1日在9:02

#3 楼

要注意的是,如果当前目录中没有可用目录,那么choroba的解决方案虽然很优雅,但却会引起意外的行为。在这种状态下,bash不会跳过for循环,而是会在d等于*/的情况下仅运行一次循环:

#!/usr/bin/env bash

for d in */; do
    # Will print */ if no directories are available
    echo "$d"
done


我建议使用以下内容来防止在这种情况下:此代码将循环遍历当前目录中的所有文件,检查f是否为目录,然后在条件返回true时回显f。如果f等于*/,则不会执行echo "$f"

评论


购物-s nullglob要容易得多。

–乔罗巴
16年6月23日在7:14

#4 楼

如果您需要选择的文件比仅目录更多,请使用find并将其传递给while read

shopt -s dotglob
find * -prune -type d | while IFS= read -r d; do 
    echo "$d"
done


使用shopt -u dotglob排除隐藏目录(或zsh中的setopt dotglob / unsetopt dotglob) 。

IFS=避免拆分包含$IFS之一的文件名,例如:'a b'

有关更多find选项,请参见下面的AsymLabs答案


编辑:
如果需要从while循环中创建退出值,则可以通过以下技巧绕开多余的子外壳:

while IFS= read -r d; do 
    if [ "$d" == "something" ]; then exit 1; fi
done < <(find * -prune -type d)


评论


我在以下位置找到了此解决方案:stackoverflow.com/a/8489394/1069083

–rubo77
13-10-22在5:06



#5 楼

您可以为此使用纯bash,但最好使用find:

find . -maxdepth 1 -type d -exec echo {} \;


(另外查找会包含隐藏目录)

评论


请注意,它不包含指向目录的符号链接。您可以将shopt -s dotglob用于bash来包含隐藏目录。您还将包括..还应注意,-maxdepth不是标准选项(-prune是)。

–StéphaneChazelas
13年8月14日在16:11

dotglob选项很有趣,但是dotglob仅适用于*。找 。将始终包含隐藏目录(以及当前目录)

–rubo77
13-10-22在5:28



#6 楼

这样做是为了在当前工作目录中查找可见目录和隐藏目录,而不是查找根目录:

循环浏览目录:

 find -path './*' -prune -type d


在结果中包括符号链接:

find -L -path './*' -prune -type d


对每个目录进行某些操作(不包括符号链接):

find -path './*' -prune -type d -print0 | xargs -0 <cmds>


排除隐藏目录:

find -path './[^.]*' -prune -type d


对返回的值执行多个命令(非常人为的示例):

find -path './[^.]*' -prune -type d -print0 | xargs -0 -I '{}' sh -c \
"printf 'first: %-40s' '{}'; printf 'second: %s\n' '{}'"


代替'sh -c'也可以使用'bash -c'等。

评论


如果回显* /中的for d中的回显'* /'包含60,000个目录,会发生什么情况?

– AsymLabs
13-10-21在4:05



您将收到“ Too many files”错误,但可以解决:如何在debian中规避“ Too many open files”

–rubo77
13-10-21在4:09



xargs示例仅适用于目录名称9e.g的子集。那些带有空格或换行符的行将无效)。更好地使用... -print0 | xargs -0 ...如果您不知道确切名称是什么。

–安东
13-10-21在4:50

@ rubo77添加了排除隐藏文件/目录和执行多个命令的方法-当然,这也可以通过脚本来完成。

– AsymLabs
13-10-21在11:22

我在底部的答案中添加了一个示例,该示例如何使用带有find * |的函数对每个目录执行操作在读取文件时;做...

–rubo77
13-10-22在4:37

#7 楼

您可以在一行中循环浏览所有目录,包括隐藏目录(以点开头)和使用以下命令的多个命令:

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



注意:使用列表*/ .*/在bash中有效,但也显示文件夹...,而在zsh中则不会显示这些文件夹,但如果存在则抛出错误文件夹中没有隐藏文件

更干净的版本将包含隐藏目录并排除../,将带有dotglob选项:

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


(或zsh中的setopt dotglob

您可以使用

shopt -u dotglob

取消设置dotglob

#8 楼

这将包括列表中每个目录中的完整路径:

for i in $(find $PWD -maxdepth 1 -type d); do echo $i; done


评论


使用带空格的文件夹时会中断

–亚历杭德罗·萨佐(Alejandro Sazo)
16-10-24在2:15

#9 楼

使用find-exec循环浏览目录并在exec选项中调用函数:

dosomething () {
  echo "doing something with "
}
export -f dosomething
find -path './*' -prune -type d -exec bash -c 'dosomething "q4312078q"' {} \;


使用shopt -s dotglobshopt -u dotglob包括/排除隐藏目录

#10 楼

这列出了给定路径中的所有目录以及子目录的数量:

for directory in */ ; do D=$(readlink -f "$directory") ; echo $D = $(find "$D" -mindepth 1 -type d | wc -l) ; done


#11 楼

ls -d */ | while read d
do
        echo $d
done


评论


这是一个名称中带有空格的目录-但会被解析为多个。

– Piskvor离开了建筑物
19-3-28在11:35



#12 楼

ls -l | grep ^d


或:

ll | grep ^d


您可以将其设置为别名

评论


不幸的是,我认为这不能回答这个问题,即“我只想遍历目录”,这与基于ls的列出目录的回答略有不同。

– Jeff Schaller♦
17年9月11日在20:26

解析ls的输出绝不是一个好主意:mywiki.wooledge.org/ParsingLs

– codeforester
18年8月21日在18:38