Answers:
for D in `find . -type d`
do
//Do whatever you need with D
done
find如果要递归或非递归行为,则需要调整参数。
find . -mindepth 1 -type d
mkdir 'directory name with spaces'分为四个单独的词。
-mindepth 1 -maxdepth 1或者它太深了。
避免创建子流程的版本:
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
if或[用:for D in */; do
for D in *; do [ -d "${D}" ] && my_command; done或两个最新命令的组合:for D in */; do [ -d $D ] && my_command; done
for D in .* *; do改用for D in *; do。
最简单的非递归方法是:
for d in */; do
echo "$d"
done
将/在年底告诉,只使用目录。
不需要
shopt -s dotglob在扩展通配符时可以用来包含dotfiles / dotdirs。参见:gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
/*,而不是*/与/代表您要使用的路径。
/*用于绝对路径,*/但包括当前位置的子目录
${d%/*}
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"; }
为了获得递归效果,请尝试使用扩展球形(**/)(启用:)shopt -s extglob。
有关更多示例,请参见:如何转到每个目录并执行命令?在SO
-exec {} +是POSIX指定的,-exec sh -c 'owd=$PWD; for arg; do cd -- "$arg" && pwd -P; cd -- "$owd"; done' _ {} +是另一个合法选项,并且调用的shell少于-exec sh -c '...' {} \;。
方便的单线
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
my_command。
这将创建一个子shell(这意味着当while循环退出时变量值将丢失):
find . -type d | while read -r dir
do
something
done
这不会:
while read -r dir
do
something
done < <(find . -type d)
如果目录名称中有空格,则任何一种都将起作用。
find ... -print0和while IFS="" read -r -d $'\000' dir
-d ''对bash语法和功能的误导性较小,因为-d $'\000'隐含(错误地)$'\000'有所不同''-实际上,一个人可以轻易地(再一次错误地)推断出bash支持Pascal样式的字符串(指定长度,能够包含NUL文字),而不是C字符串(NUL分隔,不能包含NUL)。
您可以尝试:
#!/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:仅查找最大递归深度为1(仅子目录为$ 1)和最小深度为1(不包括当前文件夹.)的目录
cd "$f"。当from的输出find是字符串拆分时,它不起作用,因此您将名称的不同部分作为中的单独值$f,从而可以更好地理解或不引用$f的扩展模拟。
find的输出是面向行的(从理论上讲,它是行的名称,但请参见下文),且具有默认-print操作。
find -print,不是传递任意文件名的安全方法,因为一个人可以运行某些文件mkdir -p $'foo\n/etc/passwd\nbar'并获得/etc/passwd名称中带有单独一行的目录。毫不费力地处理文件/upload或/tmp目录中文件的名称是获得特权升级攻击的好方法。
如果目录名称包含空格,则可接受的答案将在空格上中断,并且首选语法是$()bash / ksh。使用GNU find -exec 选项,+;例如
find .... -exec mycommand +; #this is same as passing to xargs
或使用while循环
find .... | while read -r D
do
...
done
find -exec和传递给之间有一个微妙的区别xargs:find将忽略正在执行的命令的退出值,而xargs在非零退出时失败。可能是正确的,具体取决于您的需求。
find ... -print0 | while IFS= read -r d更安全-支持以空格开头或结尾的名称,以及包含换行文字的名称。
mkdir 'foo * bar'会造成foo和bar即使要遍历它们不存在,并且*将被所有文件名(甚至非目录文件名)的列表替换)。