我在Linux上用bash编写脚本,需要遍历给定目录中的所有子目录名称。如何遍历这些目录(并跳过常规文件)?
例如:
给定目录是/tmp/
它具有以下子目录:/tmp/A, /tmp/B, /tmp/C
我想检索A,B,C。
我在Linux上用bash编写脚本,需要遍历给定目录中的所有子目录名称。如何遍历这些目录(并跳过常规文件)?
例如:
给定目录是/tmp/
它具有以下子目录:/tmp/A, /tmp/B, /tmp/C
我想检索A,B,C。
Answers:
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'
简短说明:
find
查找文件(很明显)
.
是当前目录,cd
位于后面/tmp
(恕我直言,它比/tmp
直接包含在find
命令中更为灵活。cd
如果要在此文件夹中执行更多操作,则只能更改一个位置,)。
-maxdepth 1
并-mindepth 1
确保find
仅在当前目录中查找,并且不将.
自身包含在结果中
-type d
只查找目录
-printf '%f\n
对于每次匹配,仅打印找到的文件夹名称(加上换行符)。
等等!
while..done
循环中,您可能会发疯。
find
的-exec
选项可让您为每个文件/目录运行任何命令。
到目前为止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/*/
,明智的做法是包括检查目录是否实际存在。
您可以使用以下方法遍历所有目录,包括隐藏目录(以点开头):
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 | 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
是在同一外壳中进行的,这就是为什么在我的命令中,我们必须使用来返回到当前目录popd
。
可以构建的最小bash循环(基于ghostdog74答案)
for dir in directory/*
do
echo ${dir}
done
按目录压缩一堆文件
for dir in directory/*
do
zip -r ${dir##*/} ${dir}
done
directory
,而不仅仅是子目录。
如果要在for循环中执行多个命令,可以将find
with mapfile
(bash> = 4)的结果另存为变量,然后使用遍历数组${dirlist[@]}
。它也适用于包含空格的目录。
该find
命令基于Boldewyn 的答案。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