我在Linux上用bash编写脚本,需要遍历给定目录中的所有子目录名称.如何遍历这些目录(并跳过常规文件)?
例如:
 
给定目录是否/tmp/
具有以下子目录:/tmp/A, /tmp/B, /tmp/C
我想要检索A,B,C.
gho*_*g74 412
到目前为止所有答案都使用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
Bol*_*wyn 121
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 每次点击仅打印找到的文件夹名称(加上换行符).
瞧!
rub*_*o77 39
你可以循环遍历所有目录,包括隐藏的directrories(以点开头):
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
zpo*_*pon 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
我经常使用的技术是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.所以我用过(来自维基百科):
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.  
如果要在 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
(cd /tmp; for d in */; do echo "${d%/}"; done)
无需使用外部程序。您需要的是 shell 通配模式。为了避免/tmp事后删除,我在子 shell 中运行它,这可能适合也可能不适合您的目的。
*匹配任何非空字符串任意次。?精确匹配一个字符。[...]与括号之间的字符匹配。您还可以指定范围([a-z]、[A-F0-9]等)或类([:digit:]、[:alpha:]等)。[^...]匹配不在大括号之间的字符之一。* 如果没有文件名与模式匹配,shell 将返回模式不变。任何不属于上述字符或字符串的字符或字符串均代表其自身。
因此,该模式*/将匹配任何以/. /文件名中的尾部明确标识一个目录。
最后一位是删除尾部斜杠,这是通过变量替换实现的${var%PATTERN},它从 中包含的字符串末尾删除最短的匹配模式var,其中PATTERN是任何有效的通配模式。所以我们写${d%/},这意味着我们要从 表示的字符串中删除尾部斜杠d。