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

例如: 指定目录为/tmp/ 目录包括:/tmp/A、/tmp/B、/tmp/C

我想找回A B C。


当前回答

你可以循环遍历所有目录,包括隐藏目录(以点开始):

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

其他回答

我最常用的技术是找到|个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);做的东西;完成,但是对于名称中有空格的目录是安全的。另外,对stuff的单独调用是在同一个shell中进行的,这就是为什么在我的命令中,我们必须使用popd返回到当前目录。

处理包含空格的目录

灵感来自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

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

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

按目录压缩一大堆文件

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

你可以循环遍历所有目录,包括隐藏目录(以点开始):

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
find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"