[英]Looping over directories in Bash
我有一个关于bash如何工作的基本问题,以及一个相关的实际问题。
基本问题:假设我在一个有三个子目录的目录中:a,b和c。
母鸡的代码
for dir in $(ls)
do
echo $dir
done
吐出:
a b c
a b c
a b c
即, dir
始终存储我的cwd
中所有文件/目录的列表。 我的问题是:为什么世界会这么方便? 在我看来,让dir
存储每个元素更有用和直观,即我想要输出
a
b
c
另外,根据其中一个答案 - for dir in $(ls)
使用for dir in $(ls)
是错误的,但是当我for dir in $(ls -l)
使用for dir in $(ls -l)
我得到更多的abc
副本(比目录/文件更多)在cwd)。 这是为什么?
我的第二个问题是实用的:如何在我的cwd
中以大写cwd
W开头的所有目录(不是文件!)循环? 我开始了
for dir in `ls -l W*`
但这失败了因为a)问题1和b)中的原因,因为它不排除文件。 建议表示赞赏。
永远不要像这样解析ls
的输出( 为什么你不应该解析ls(1)的输出 )。
另外,你的语法错了。 你不是指()
,你的意思是$()
。
话虽这么说,要循环使用W开头的目录(或者使用find
命令,具体取决于你的场景):
for path in /my/path/W*; do
[ -d "${path}" ] || continue # if not a directory, skip
dirname="$(basename "${path}")"
do_stuff
done
至于你从邪恶的ls循环得到的输出,它应该看起来不那样。 这是预期的输出,并说明了为什么你不想首先使用ls:
$ find
.
./c
./a
./foo bar
./b
$ type ls
ls is hashed (/bin/ls)
$ for x in $(ls); do echo "${x}"; done
a
b
c
foo
bar
这应该工作:
shopt -s nullglob # empty directory will return empty list
for dir in ./*/;do
echo "$dir" # dir is directory only because of the / after *
done
要在子目录中递归,请使用globstar
:
shopt -s globstar nullglob
for dir in ./**/;do
echo "$dir" # dir is directory only because of the / after **
done
您可以@AdrianFrühwirths'的方法是递归通过使用子目录globstar
太:
shopt -s globstar
for dir in ./**;do
[[ ! -d $dir ]] && continue # if not directory then skip
echo "$dir"
done
globstar
如果设置,则文件名扩展上下文中使用的模式“**”将匹配所有文件以及零个或多个目录和子目录。 如果模式后跟'/',则只有目录和子目录匹配。
了nullglob
如果设置,Bash允许不匹配任何文件的文件名模式扩展为空字符串,而不是自己。
嗯,你知道你所看到的并不是你所期待的。 您看到的输出不是来自echo命令,而是来自dir命令。
请尝试以下方法:
ls -1 | while read line; do
if [-d "$line" ] ; then
echo $line
fi
done
for files in $(ls) ; do
if [-d "$files" ] ; then
echo $files
fi
done
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.