Bash:对于每个目录

mik*_*son 181 bash command directory-traversal

我正在处理需要在特定文件夹的每个子目录中执行操作的脚本.

写这个最有效的方法是什么?

kan*_*aka 268

避免创建子流程的版本:

for D in *; do
    if [ -d "${D}" ]; then
        echo "${D}"   # your processing here
    fi
done
Run Code Online (Sandbox Code Playgroud)

或者,如果您的操作是单个命令,则更简洁:

for D in *; do [ -d "${D}" ] && my_command; done
Run Code Online (Sandbox Code Playgroud)

或者更简洁的版本(感谢@enzotib).请注意,在此版本中,每个值D都有一个尾部斜杠:

for D in */; do my_command; done
Run Code Online (Sandbox Code Playgroud)

  • 您可以在*/中避免使用`if`或`[`with:`for D; do` (47认同)
  • 最后一个命令有一个问题:如果你在没有子目录的目录中; 它将返回"*/".所以最好使用第二个命令`for D in*; 做[-d"$ {D}"] && my_command; 完成`或最近两个的组合:`for D in*/; 做[-d $ D] && my_command; done` (5认同)
  • 请注意,此答案忽略隐藏的目录.要包含隐藏目录,请使用`for D in.**; do`而不是'for D in*; do`. (5认同)
  • 即使是目录名+1中的空格,这个也是正确的 (3认同)
  • +1是因为目录名称不是以./开头,而不是接受的答案 (2认同)
  • @Hafthor `${D%/}` 可能更安全,因此 `/` 之后的额外字符不会被意外删除。 (2认同)

Mik*_*ark 167

for D in `find . -type d`
do
    //Do whatever you need with D
done
Run Code Online (Sandbox Code Playgroud)

  • 这将打破白色空间 (80认同)
  • 上面的回答也给了我自己的目录,所以以下对我来说效果更好:`find.-mindepth 1-type d` (29认同)
  • 我需要添加`-mindepth 1 -maxdepth 1`或它太深了。 (3认同)
  • 另外,请注意,如果您想要递归或非递归行为,则需要调整 `find` 参数。 (2认同)

d0x*_*d0x 95

最简单的非递归方式是:

for d in */; do
    echo "$d"
done
Run Code Online (Sandbox Code Playgroud)

/在年底告诉,只使用目录.

没有必要

  • AWK
  • ...

  • 注意:这不包括点dirs(这可能是一件好事,但重要的是要知道). (8认同)
  • 有用的提示:如果您需要从 $d 中删除尾随的“/”,请使用“${d%/*}” (4认同)
  • @Shule `/*` 将用于绝对路径,而 `*/` 将包含当前位置的子目录 (2认同)

ken*_*orb 15

使用find命令.

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

find . -type d -execdir realpath "{}" ';'
Run Code Online (Sandbox Code Playgroud)

或者使用-exec参数:

find . -type d -exec sh -c 'cd -P "$0" && pwd -P' {} \;
Run Code Online (Sandbox Code Playgroud)

或者用xargs命令:

find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'
Run Code Online (Sandbox Code Playgroud)

或者使用for循环:

for d in */; { echo "$d"; }
Run Code Online (Sandbox Code Playgroud)

对于递归,请尝试使用扩展的globbing(**/)(启用by :) shopt -s extglob.


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


Sri*_*ali 12

方便的单行

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

find * -type d ### Option B
Run Code Online (Sandbox Code Playgroud)

选项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
Run Code Online (Sandbox Code Playgroud)


Pau*_*lin 9

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


Pau*_*ce. 7

这将创建一个子shell(这意味着当while循环退出时变量值将丢失):

find . -type d | while read -r dir
do
    something
done
Run Code Online (Sandbox Code Playgroud)

这不会:

while read -r dir
do
    something
done < <(find . -type d)
Run Code Online (Sandbox Code Playgroud)

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


gho*_*g74 6

如果目录名称有空格,则接受的答案将在空格处中断,并且首选语法是$()bash/ksh。使用GNU find -exec 选项与+;例如

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

或使用 while 循环

find .... | while read -r D
do
    # use variable `D` or whatever variable name you defined instead here
done 
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以尝试:

#!/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
Run Code Online (Sandbox Code Playgroud)

或类似...

说明:

find . -maxdepth 1 -mindepth 1 -type d:仅查找最大递归深度为1(仅子目录为$ 1)且最小深度为1(不包括当前文件夹.)的目录