4

中,我想获取以下唯一子文件夹的名称a

cd /tmp; mkdir -p a/b; v=$(ls -1 a); echo "$v"

输出:

b

这就是我想要的。

这行得通,因为我知道里面只有一个子文件夹a

随意假设在我的场景中的所有情况下都可以保证这一点。

让我感到不安的是,这个来自Bash pitfalls的建议

In addition to this, the use of ls is just plain unnecessary.
It's an external command whose output is intended specifically
to be read by a human, not parsed by a script.

这更加令人生畏和精巧(来自与上面相同的链接):


解析 ls 的输出——一个永远不应该解析其输出的实用程序。


它引起了我的共鸣,但这是尝试使用 globbing,obv。不起作用:

 cd /tmp; mkdir -p a/b; v=a/*; echo "$v"

输出:

a/*

悲伤。

那么,我怎样才能得到一个变量赋值的通配符呢?

我知道如何在分配之外利用globbing ..

for d in a/*; do echo "$(basename $d)"; done

输出:

b

“正确答案”(TM)。

请您教我如何正确执行此操作并解释其背后的原理,好吗?

** 注意:我不喜欢这个命令的输出:**

cd /tmp; w='name with blanks'; mkdir -p "$w/b"; v=$(echo "$w"/*); echo "$v"

这是:

name with blanks/b

我只想得到:

b

之后我必须使用basename,还是我可以b直接得到,不知何故?

4

2 回答 2

4
v=$(cd a;echo *)

通配符在命令替换中扩展,echo并将输出它以便在分配中使用。

cd将允许您只获取基本名称而无需调用basename.

于 2013-04-04T03:05:11.707 回答
4

很确定我写了那个陷阱句子。无论如何...您的失败是因为大括号扩展、glob 和分词不适用于标量分配。

printf -v v %s */

还有一个鲜为人知的技巧,只能使用 coreutils printf(1)(假设有多个目录)。

v=$(LC_COLLATE=C; /usr/bin/printf '%s\c' */)

或者,这可能最接近您所追求的(GNU 查找):

v=$(find . -maxdepth 1 -type d -name '[^.]?*' -printf %f -quit)

另见: http: //mywiki.wooledge.org/ParsingLs

于 2013-04-04T11:55:03.610 回答