【发布时间】:2011-01-07 15:42:07
【问题描述】:
我正在 Linux 上用 bash 编写脚本,需要遍历给定目录中的所有子目录名称。如何遍历这些目录(并跳过常规文件)?
例如:
给定目录是/tmp/
它有以下子目录:/tmp/A, /tmp/B, /tmp/C
我想检索 A、B、C。
【问题讨论】:
我正在 Linux 上用 bash 编写脚本,需要遍历给定目录中的所有子目录名称。如何遍历这些目录(并跳过常规文件)?
例如:
给定目录是/tmp/
它有以下子目录:/tmp/A, /tmp/B, /tmp/C
我想检索 A、B、C。
【问题讨论】:
到目前为止,所有答案都使用find,所以这里只有一个外壳。在您的情况下不需要外部工具:
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
【讨论】:
find
for dir in */; do echo $dir; done 用于当前目录中的目录。
dir=${dir%*/} 和 echo ${dir##*/} 正在做什么的解释,那就太好了。
/tmp/*/触发,明智的做法是检查目录是否真的存在。
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'
简短说明:
find 查找文件(很明显)
. 是当前目录,在cd 之后是/tmp (恕我直言,这比在find 命令中直接使用/tmp 更灵活。你只有一个地方,即cd,如果您想在此文件夹中执行更多操作,请更改)
-maxdepth 1 和 -mindepth 1 确保 find 只在当前目录中查找,而不在结果中包含 . 本身
-type d 仅查找目录
-printf '%f\n 仅打印每次点击找到的文件夹的名称(加上换行符)。
等等!
【讨论】:
while..done 循环内你会发疯的。
find 的 -exec 选项允许您为每个文件/目录运行任何命令。
您可以使用以下命令遍历所有目录,包括隐藏目录(以点开头):
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"
【讨论】:
basename。我更喜欢这个而不是我的答案。
我最常使用的技术是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。所以我使用了(来自Wikipedia):
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 返回到当前目录的原因。
【讨论】:
您可以构建的最小 bash 循环(基于 ghostdog74 答案)
for dir in directory/*
do
echo ${dir}
done
按目录压缩一大堆文件
for dir in directory/*
do
zip -r ${dir##*/} ${dir}
done
【讨论】:
directory的所有文件,而不仅仅是子目录。
如果你想在一个for循环中执行多个命令,你可以将find和mapfile(bash >= 4)的结果保存为一个变量,然后用${dirlist[@]}遍历数组。它也适用于包含空格的目录。
find 命令基于 Boldewyn 的 answer。有关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
【讨论】:
find . -type d -maxdepth 1
【讨论】: