Bash:为每个目录

我正在研究需要在特定文件夹的每个子目录中执行操作的脚本。

什么是最有效的方式来写呢?

for D in `find . -type d` do //Do whatever you need with D done 

避免创build子stream程的版本:

 for D in *; do if [ -d "${D}" ]; then echo "${D}" # your processing here fi done 

或者,如果你的行动是一个单一的命令,这更简洁:

 for D in *; do [ -d "${D}" ] && my_command; done 

或更简洁的版本( 谢谢@enzotib )。 请注意,在这个版本中, D每个值都会有一个斜杠:

 for D in */; do my_command; done 

最简单的非recursion方式是:

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

/最后告诉,只使用目录。

没有必要

  • AWK

方便的单线

 for D in *; do echo "$D"; done for D in *; do find "$D" -type d; done ### Option A find * -type d ### Option B 

选项A适用于有空格的文件夹。 此外,通常更快,因为它不会将文件夹名称中的每个单词作为单独的实体进行打印。

 # Option A $ time for D in ./big_dir/*; do find "$D" -type d > /dev/null; done real 0m0.327s user 0m0.084s sys 0m0.236s # Option B $ time for D in `find ./big_dir/* -type d`; do echo "$D" > /dev/null; done real 0m0.787s user 0m0.484s sys 0m0.308s 

find . -type d -print0 | xargs -0 -n 1 my_command

使用find命令。

在GNU find ,你可以使用-execdir参数:

 find . -type d -execdir realpath "{}" ';' 

或者使用-exec参数:

 find . -type d -exec sh -c 'cd -P "$0" && pwd -P' {} \; 

或用xargs命令:

 find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff' 

或者使用for循环:

 for d in */; { echo "$d"; } 

对于recursion,尝试扩展globbing( **/ ),而不是(启用: shopt -s extglob )。


有关更多示例,请参阅: 如何前往每个目录并执行命令? 在SO

这将创build一个子shell(这意味着当while循环退出时,variables值将会丢失):

 find . -type d | while read -r dir do something done 

这不会:

 while read -r dir do something done < <(find . -type d) 

如果目录名称中有空格,任何一个都可以工作。

你可以尝试:

 #!/bin/bash ### $1 == the first args to this script ### usage: script.sh /path/to/dir/ for f in `find . -maxdepth 1 -mindepth 1 -type d`; do cd "$f" <your job here> done 

或类似…

说明:

find . -maxdepth 1 -mindepth 1 -type d find . -maxdepth 1 -mindepth 1 -type d :只能find最大recursion深度为1的目录(只有$ 1的子目录)和最小深度为1(不包括当前文件夹) .

如果目录名具有这些空格,则接受的答案将在空格上打破,而对于bash / ksh,首选语法是$() 。 使用GNU find -exec选项+; 例如

find .... -exec mycommand +; #this is same as passing to xargs

或者使用一个while循环

 find .... | while read -r D do ... done