代码之家  ›  专栏  ›  技术社区  ›  Robottinosino

Bash编程:获取给定目录中唯一一个子文件夹的名称

  •  4
  • Robottinosino  · 技术社区  · 12 年前

    在里面 ,我想知道的唯一一个子文件夹的名称 a :

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

    输出:

    b
    

    这正是我想要的。

    这很有效,因为我 知道 里面只有一个子文件夹 .

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

    我感到不安的是,来自 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的输出——一个永远不应该解析其输出的实用程序。


    这引起了我的共鸣,但这是一个 企图 使用时 球形,obv.不起作用:

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

    输出:

    a/*
    

    悲伤

    那么,我该怎么办 通配符 变量赋值?

    认为 我知道如何利用 通配符 不在任务范围内。。

    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 直接,不知怎么的?

    2 回复  |  直到 12 年前
        1
  •  4
  •   ormaaj    12 年前

    很肯定我写了那个陷阱句。无论如何您的失败是因为大括号展开、globs和分词不适用于标量赋值。

    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

        2
  •  4
  •   Barmar    12 年前
    v=$(cd a;echo *)
    

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

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