以下两行都会返回我的目录之一的目录列表。
第一个使用名称模式,而我需要选择目录,因为它们实际上是目录,然后在循环中处理它们。因此我想使用第二个:
ls -l | awk '{print $9}' | grep 'dirsPrefix*'
find . -maxdepth 1 -type d | grep -v \\.$ | awk -F'./' '{print $2}'
但在 ksh for 循环中,第一个的工作方式与第二个不同......为什么? :
(解决方法:
for dir in `find . -maxdepth 1 -type d -exec echo "{}" \; | awk -F'/' {print $2}`
do
echo "dir: $dir"
done
将工作)
这也有效:
for dir in `ls -l | awk '{print $9}' | grep 'dirsPrefix*'`
do
echo "dir: $dir"
done
但这并不:
for dir in `find . -maxdepth 1 -type d | grep -v \\.$ | awk -F'./' '{print $2}'`
do
echo "dir: $dir"
done
答案1
您太努力地尝试获取当前目录中的目录。您需要做的就是:
for dir in */; do echo "dir: $dir"; done
# .........^^
如果你想将它们存储在数组中:
dirs=( */ )
答案2
改成这样:
for dir in $(find . -maxdepth 1 -type d | grep -v \\.$ | awk -F'./' '{print $2}')
do
echo "dir: $dir"
done
我无法解释为什么它有效,但我知道你应该总是使用$()
反引号。
答案3
您需要意识到您正在运行的命令,即,
for dir in `find . -maxdepth 1 -type d | grep -v \\.$ | awk -F'./' '{print $2}'`
报价解释有两个级别。在第一级中,即发出命令的命令行级别,首先扫描反引号“....”下的文本中的反斜杠和 $ 变量,就像双引号插值一样。由于那$
是孤独的最后,所以不会展开。不过,逃避也没有什么坏处。
所以这将留下grep -v \\.$ ----> grep -v \.$
现在这一步结束后,就要交给子shell来运行了。在该子 shell 中,将解析命令grep -v \.$
并删除反斜杠,因此grep
在此阶段结束时可执行文件得到的是: grep -v .$
现在所有非空行将匹配此模式并查找生成的所有非空行,原因很简单,文件名不能为非空。
因此,这意味着find
将选择所有输出,因此相反,意味着不应选择 find 的任何输出。所以 awk 已经盛装打扮了,但确实无处可去。
解决方案:
您可以采取很多措施来解决该问题。
- 在 grep 中再添加一个反斜杠,使其成为:
grep -v \\\.$
根据此场景中引号扩展的每个步骤中发生的情况,确信此修复有效。 - 使用 $() 形式的命令插值,因为在此格式中,引用以 $() 重新开始,这与反引用的 `` 形式不同。
- 在 grep 中使用单引号,使其:
grep -v '\.$'
- 使用字符类来转义 . :
grep -v '[.]$'
find
在命令本身中完成所有操作:
find . -maxdepth 1 -type d ! -name . -exec sh -c '
for d do printf "dir: %s\n" "${d:2}"; done
' sh {} +
答案4
你的 - 表达式有问题grep
。它将匹配所有以 结尾的目录名称.
,但它似乎也会以某种方式扭曲输出以造成for
混淆。对此您可以做很多事情。
将 grep 表达式更改为
grep -v "^\.$"
可能会更正确(因为它将仅匹配.
目录),并且它将在您的for
-loop中工作正如@Jesse_b 已经指出的那样,出于多种原因,最好使用表达式
$(..)
来执行。这将解决您眼前的问题,但无法修复潜在的错误。您可以
find
一路使用,使这个脚本更简单一些:for dir in `find . -maxdepth 1 -type d ! -name "." -printf "%f "` do echo $dir done
如果存在名称中带有空格 ( ) 的目录,则所有这些解决方案都不会出现问题。