【问题标题】:Listing only directories using ls in Bash?在 Bash 中仅使用 ls 列出目录?
【发布时间】:2012-12-30 09:51:27
【问题描述】:

此命令列出当前路径中的目录:ls -d */

*/ 模式究竟做了什么?

我们如何在上述命令中给出绝对路径(例如ls -d /home/alice/Documents),以便仅列出该路径中的目录?

【问题讨论】:

    标签: bash directory ls


    【解决方案1】:

    */ 是匹配当前目录中所有子目录的模式(* 将匹配所有文件 子目录;/ 将其限制为目录)。同样,要列出 /home/alice/Documents 下的所有子目录,请使用 ls -d /home/alice/Documents/*/

    【讨论】:

    • 请注意,*/ 不会匹配任何隐藏文件夹。要包含它们,可以像 ls -d .*/ */ 或 Bash 中的 set the dotglob option 那样明确指定它们。
    • @GordonDavisson 使用 bash 选项可以避免失败消息shopt -s nullglob
    • @BinaryZebra 设置 nullglob 将避免错误消息,但会导致更多混乱:设置 nullglob 且没有子目录,ls */ 将扩展为仅 ls,这将列出所有文件当前目录。在这种情况下,我很确定这不是您想要的。
    • */ 还设置子目录的名称以斜杠结尾。
    • 列出所有文件夹,不包括./ ../: ls -d */ .[^.]*/
    【解决方案2】:

    完成此任务的四种方法,每种方法都有不同的输出格式

    1。使用echo

    示例:echo */echo */*/
    这是我得到的:

    cs/ draft/ files/ hacks/ masters/ static/  
    cs/code/ files/images/ static/images/ static/stylesheets/  
    

    2。仅使用ls

    示例:ls -d */
    这正是我得到的:

    cs/     files/      masters/  
    draft/  hacks/      static/  
    

    或作为列表(带有详细信息):ls -dl */

    3。使用lsgrep

    示例:ls -l | grep "^d" 这是我得到的:

    drwxr-xr-x  24 h  staff     816 Jun  8 10:55 cs  
    drwxr-xr-x   6 h  staff     204 Jun  8 10:55 draft  
    drwxr-xr-x   9 h  staff     306 Jun  8 10:55 files  
    drwxr-xr-x   2 h  staff      68 Jun  9 13:19 hacks  
    drwxr-xr-x   6 h  staff     204 Jun  8 10:55 masters  
    drwxr-xr-x   4 h  staff     136 Jun  8 10:55 static  
    

    4。 Bash 脚本(不推荐用于包含空格的文件名)

    示例:for i in $(ls -d */); do echo ${i%%/}; done
    这是我得到的:

    cs  
    draft  
    files  
    hacks  
    masters  
    static
    

    如果你喜欢用'/'作为结束符,命令是:for i in $(ls -d */); do echo ${i}; done

    cs/  
    draft/  
    files/  
    hacks/  
    masters/  
    static/
    

    【讨论】:

    • NB. 3 对我来说明显比其他人慢。在我测试的目录中:1.012s,2.016s,3.055s,4.021s.
    • @isomorphismes,你是如何测量时间的?怎么做?顺便说一句,我不得不说,不。1是我的最爱。
    • Albert,我使用了time,Unix 函数。 /// 我同意,echo */ls -d */ 聪明。
    • 您应该注意的两件小事。 ls -l | grep "^d" 过滤掉目录的符号链接,而 'ls -d */' 显示它们。此外,如果目标目录中根本不存在任何目录,则“ls -d */”会失败。
    • 1. 选项在处理包含空格的文件夹名称时会带来很大的麻烦。
    【解决方案3】:

    我用:

    ls -d */ | cut -f1 -d'/'
    

    这会创建一个不带斜杠的单列 - 在脚本中很有用。

    【讨论】:

    • ls-1 选项也将以单列格式输出,如ls -1 -d */
    • @user29020 应该注意-1 仍然为每个条目输出一个斜杠。
    • 当我将此添加到.bashrc 作为别名时,如何添加'/'
    • @RNA 迟到了回答,但对于未来的人:尝试用反斜杠转义? '\/'
    • 如果有前导斜线则中断。这仅删除尾部斜杠:| sed -e 's-/$--'
    【解决方案4】:

    对于所有没有子文件夹的文件夹:

    find /home/alice/Documents -maxdepth 1 -type d
    

    对于所有带有子文件夹的文件夹:

    find /home/alice/Documents -type d
    

    【讨论】:

    • 要匹配问题(但包括点文件),第一个应该是:find /home/alice/Documents -maxdepth 1 -mindepth 1 -type d 否则你包括 /home/alice/Documents 本身。要包含指向目录的符号链接,请以 -L 为前缀
    • 这似乎是最明智的解决方案,因为 find 是实际为此任务而设计的工具。您可以通过管道排除第一个结果 - 当前目录的 ./ - grep -v '^\./$'
    【解决方案5】:

    四个(更多)可靠选项。

    未引用星号* 将被shell 解释为模式(glob)。 shell 将在路径名扩展中使用它。然后它将生成与该模式匹配的文件名列表。

    一个简单的星号将匹配 PWD(当前工作目录)中的所有文件名。像*/ 这样更复杂的模式将匹配所有以/ 结尾的文件名。因此,所有目录。这就是为什么命令:

    1.- 回声。

    echo */
    echo ./*/              ### Avoid misinterpreting filenames like "-e dir"
    

    将(通过 shell)扩展为 echo PWD 中的所有目录。


    要对此进行测试:创建一个名为 test-dir 的目录 (mkdir),然后将 cd 放入其中:

    mkdir test-dir; cd test-dir
    

    创建一些目录:

    mkdir {cs,files,masters,draft,static}   # Safe directories.
    mkdir {*,-,--,-v\ var,-h,-n,dir\ with\ spaces}  # Some a bit less secure.
    touch -- 'file with spaces' '-a' '-l' 'filename'    # And some files:
    

    命令echo ./*/ 将保持可靠,即使是奇怪的命名文件:

    ./--/ ./-/ ./*/ ./cs/ ./dir with spaces/ ./draft/ ./files/ ./-h/
    ./masters/ ./-n/ ./static/ ./-v var/
    

    但是文件名中的空格使阅读有点混乱。


    如果不是echo,我们使用ls。外壳仍然是扩展文件名列表的东西。 shell 是在 PWD 中获取目录列表的原因。 ls-d 选项使其列出当前目录条目,而不是每个目录的内容(默认显示)。

    ls -d */
    

    但是,这个命令(有点)不太可靠。它会因上面列出的奇怪的命名文件而失败。它会被几个名字窒息。你需要一个一个地擦除,直到找到有问题的。

    2.- ls

    GNU ls 将接受“选项结束”(--) 键。

    ls -d ./*/                     ### More reliable BSD ls
    ls -d -- */                    ### More reliable GNU ls
    

    3.-printf

    要在单独的行中列出每个目录(在一列中,类似于 ls -1),请使用:

    $ printf "%s\n" */        ### Correct even with "-", spaces or newlines.
    

    而且,更好的是,我们可以删除尾随的/

    $ set -- */; printf "%s\n" "${@%/}"        ### Correct with spaces and newlines.
    

    类似的尝试

    $ for i in $(ls -d */); do echo ${i%%/}; done
    

    将失败:

    • 上面已经显示了一些名称 (ls -d */)。
    • 会受IFS的值影响。
    • 将在空格和制表符上拆分名称(默认为IFS)。
    • 名称中的每个换行符都会启动一个新的 echo 命令。

    4.- 功能

    最后,在函数内部使用参数列表不会影响当前运行的 shell 的参数列表。简单的

    $ listdirs(){ set -- */; printf "%s\n" "${@%/}"; }
    $ listdirs
    

    提供此列表:

    --
    -
    *
    cs
    dir with spaces
    draft
    files
    -h
    masters
    -n
    static
    -v var
    

    这些选项对于几种类型的奇数文件名是安全的。

    【讨论】:

      【解决方案6】:

      tree 命令在这里也非常有用。默认情况下,它将显示所有文件和目录的完整深度,其中一些 ASCII 字符显示目录树。

      $ tree
      .
      ├── config.dat
      ├── data
      │   ├── data1.bin
      │   ├── data2.inf
      │   └── sql
      |   │   └── data3.sql
      ├── images
      │   ├── background.jpg
      │   ├── icon.gif
      │   └── logo.jpg
      ├── program.exe
      └── readme.txt
      

      但是,如果我们只想获取目录,而不需要 ASCII 树,并使用当前目录的完整路径,您可以这样做:

      $ tree -dfi
      .
      ./data
      ./data/sql
      ./images
      

      参数是:

      -d     List directories only.
      -f     Prints the full path prefix for each file.
      -i     Makes tree not print the indentation lines, useful when used in conjunction with the -f option.
      

      如果你想要绝对路径,你可以从指定当前目录的完整路径开始:

      $ tree -dfi "$(pwd)"
      /home/alice/Documents
      /home/alice/Documents/data
      /home/alice/Documents/data/sql
      /home/alice/Documents/images
      

      为了限制子目录的数量,可以用-L level设置子目录的最大级别,例如:

      $ tree -dfi -L 1 "$(pwd)"
      /home/alice/Documents
      /home/alice/Documents/data
      /home/alice/Documents/images
      

      更多参数可以通过man tree查看。

      【讨论】:

        【解决方案7】:

        如果您想知道为什么 'ls -d */' 的输出会为您提供 两个 斜杠,例如:

        [prompt]$ ls -d */
        app//  cgi-bin//  lib//        pub//
        

        这可能是因为您的 shell 或会话配置文件在某处将 ls 命令别名为包含 -F 标志的 ls 版本。该标志将一个字符附加到每个输出名称(不是纯文件),指示它的类型。所以一个斜线来自匹配模式'*/',另一个斜线是附加的类型指示符。

        要摆脱这个问题,您当然可以为 ls 定义一个不同的别名。但是,要暂时不调用别名,您可以在命令前加上反斜杠:

        \ls -d */
        

        【讨论】:

          【解决方案8】:

          实际的ls 解决方案,包括指向目录的符号链接

          这里的许多答案实际上并没有使用ls(或仅在ls -d 的琐碎意义上使用它,同时使用通配符进行实际的子目录匹配。真正的ls 解决方案很有用,因为它允许使用ls 选项进行排序等。

          排除符号链接

          已经给出了一个使用ls 的解决方案,但它与其他解决方案的不同之处在于它排除了指向目录的符号链接

          ls -l | grep '^d'
          

          (可能通过sedawk 来隔离文件名)

          包括符号链接

          在(可能更常见的)应该包含指向目录的符号链接的情况下,我们可以使用ls-p 选项,这使得它在目录名称(包括符号链接的)后面附加一个斜杠字符:

          ls -1p | grep '/$'
          

          或者,去掉尾部的斜杠:

          ls -1p | grep '/$' | sed 's/\/$//'
          

          我们可以根据需要向ls 添加选项(如果使用长列表,则不再需要-1)。

          注意:如果我们想要尾随斜杠,但不希望它们被grep 突出显示,我们可以通过将实际匹配的部分设置为空行:

          ls -1p | grep -P '(?=/$)'
          

          【讨论】:

            【解决方案9】:

            当前目录的简单列表,它是:

            ls -1d */
            

            如果你想要它排序和清洁:

            ls -1d */ | cut -c 1- | rev | cut -c 2- | rev | sort
            

            记住:大写字符在排序中具有不同的行为

            【讨论】:

              【解决方案10】:

              如果不需要列出隐藏目录,我提供:

              ls -l | grep "^d" | awk -F" " '{print $9}'
              

              如果需要列出隐藏目录,请使用:

              ls -Al | grep "^d" | awk -F" " '{print $9}'
              

              或者

              find -maxdepth 1 -type d | awk -F"./" '{print $2}'
              

              【讨论】:

              • 如果您需要了解更多关于awk的信息,请查看此answer
              • 与其他答案相比,“ls .. | grep ...| awk”的第一个选项似乎过多的脚本。
              • 您假设目录名称中没有空格。
              • ls -l | awk '/^d/ {print $9}' 这就是我想出来的 :) 既然已经竖起大拇指了!
              • ls -l | awk '/^d/ {print $9}' 有效,没有目录时其他方案无效
              【解决方案11】:

              我只是将它添加到我的.bashrc 文件中(如果您只需要/想要一个会话,您也可以在命令行中键入它):

              alias lsd='ls -ld */'
              

              然后lsd会产生想要的结果。

              【讨论】:

              • 你不能用吗? ls -l 路径 | grep 博士
              • "那么 lsd 会产生想要的结果。"我笑了
              • 根据我的经验,它会产生结果。
              • 我使用 'lad' (列出所有目录),我还包括了 '.*/' 来包括隐藏目录。当然,我也不会失去影射。
              【解决方案12】:

              仅列出目录

              ls -l | grep ^d
              

              仅列出文件

              ls -l | grep -v ^d 
              

              或者你也可以这样做:

              ls -ld */
              

              【讨论】:

                【解决方案13】:

                显示没有/的文件夹列表:

                ls -d */|sed 's|[/]||g'
                

                【讨论】:

                • ls -d1 */ | tr -d "/"
                • 无需调用外部命令:set -- */; printf "%s\n" "${@%/}"
                • 我喜欢@wholanda 的解决方案。我的更短的解决方案是(经过测试和工作): ls -d */|sed 's|/||g'
                • 还有一个 lsdir 别名也很有用: alias lsdirs="ls -d */ | sed 's|/||g'"
                【解决方案14】:

                试试这个。它适用于所有 Linux 发行版。

                ls -ltr | grep drw
                

                【讨论】:

                • ls -l | grep '^d' | awk '{print $9}'
                【解决方案15】:

                这是我正在使用的

                ls -d1 /Directory/Path/*;
                

                【讨论】:

                • 这其实是一个很好的解决方案,逐行显示。
                • 它不会只列出目录。您必须添加尾部斜杠:ls -d1 /Directory/Path/*/
                【解决方案16】:

                测试item是否为test -d的目录:

                for i in $(ls); do test -d $i && echo $i ; done
                

                【讨论】:

                • 请解释这段代码的作用,以及它与问题的关系。
                • 它运行命令 'ls' 然后循环输出测试,如果每个都是一个目录,如果是,则回显.. 工作但有更好的方法
                • @ShoeLace:有什么更好的方法?其中一些是否出现在此处的答案中?
                【解决方案17】:

                仅供参考,如果您想多行打印所有文件,您可以使用ls -1 将每个文件打印在单独的行中。 文件 1 文件2 文件3

                【讨论】:

                  【解决方案18】:

                  */ 是匹配当前目录中目录的文件名匹配模式。

                  只列出目录,我喜欢这个功能:

                  # Long list only directories
                  llod () {
                    ls -l --color=always "$@" | grep --color=never '^d'
                  }
                  

                  把它放在你的 .bashrc 文件中。

                  用法示例:

                  llod       # Long listing of all directories in current directory
                  llod -tr   # Same but in chronological order oldest first
                  llod -d a* # Limit to directories beginning with letter 'a'
                  llod -d .* # Limit to hidden directories
                  

                  注意:如果您使用-i 选项,它将中断。这是一个解决方法:

                  # Long list only directories
                  llod () {
                    ls -l --color=always "$@" | egrep --color=never '^d|^[[:digit:]]+ d'
                  }
                  

                  【讨论】:

                    【解决方案19】:
                    file * | grep directory
                    

                    输出(在我的机器上)--

                    [root@rhel6 ~]# file * | grep directory
                    mongo-example-master:    directory
                    nostarch:                directory
                    scriptzz:                directory
                    splunk:                  directory
                    testdir:                 directory
                    

                    上面的输出可以通过cut进一步细化:

                    file * | grep directory | cut -d':' -f1
                    mongo-example-master
                    nostarch
                    scriptzz
                    splunk
                    testdir
                    
                    * could be replaced with any path that's permitted
                     file - determine file type
                     grep - searches for string named directory
                     -d - to specify a field delimiter
                     -f1 - denotes field 1
                    

                    【讨论】:

                      【解决方案20】:

                      ls 和 awk(没有 grep)

                      不需要使用 grep,因为 awk 可以执行正则表达式检查,所以这样做就足够了:

                      ls -l | awk '/^d/ {print $9}'
                      

                      ls -l 列出具有权限的文件
                      awk 过滤输出
                      '/^d/' 正则表达式仅搜索以字母 d 开头的行(作为目录)查看第一行 - 权限
                      {print} 将打印所有列
                      {print $9} 将仅打印来自 ls -l第 9 列(名称)输出

                      非常简单干净

                      【讨论】:

                        【解决方案21】:

                        仅从“这里”列出目录。

                        有文件数。

                        for i in `ls -d */`; do g=`find ./$i -type f -print| wc -l`; echo "Directory $i contains $g files."; done
                        

                        【讨论】:

                          【解决方案22】:

                          使用 Perl:

                          ls | perl -nle 'print if -d;'
                          

                          【讨论】:

                            【解决方案23】:

                            我部分解决了:

                            cd "/path/to/pricipal/folder"
                            
                            for i in $(ls -d .*/); do sudo ln -s "$PWD"/${i%%/} /home/inukaze/${i%%/}; done
                            

                             

                                ln: «/home/inukaze/./.»: can't overwrite a directory
                                ln: «/home/inukaze/../..»: can't overwrite a directory
                                ln: accesing to «/home/inukaze/.config»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.disruptive»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/innovations»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/sarl»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.e_old»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.gnome2_private»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.gvfs»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.kde»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.local»: too much symbolics links levels
                                ln: accesing to «/home/inukaze/.xVideoServiceThief»: too much symbolics links levels
                            

                            嗯,这对我来说是主要部分:)

                            【讨论】:

                              【解决方案24】:

                              这是一个使用 tree 的变体,它只在单独的行上输出目录名称,是的,它很丑,但是嘿,它可以工作。

                              tree -d | grep -E '^[├|└]' | cut -d ' ' -f2
                              

                              或使用 awk

                              tree -d | grep -E '^[├|└]' | awk '{print $2}'
                              

                              这可能会更好,但会在目录名称后保留/

                              ls -l | awk '/^d/{print $9}'
                              

                              【讨论】:

                                【解决方案25】:

                                回答原问题,*/ls本身无关;它是由 shell/Bash 在称为 globbing 的过程中完成的。

                                这就是echo */ls -d */ 输出相同元素的原因。 (-d 标志使ls 输出目录名称而不是目录内容。)

                                【讨论】:

                                  【解决方案26】:

                                  添加以使其完整循环,检索每个文件夹的路径,使用 Albert 的答案以及 Gordans 的组合。这应该很有用。

                                  for i in $(ls -d /pathto/parent/folder/*/); do echo ${i%%/}; done
                                  

                                  输出:

                                  /pathto/parent/folder/childfolder1/
                                  /pathto/parent/folder/childfolder2/
                                  /pathto/parent/folder/childfolder3/
                                  /pathto/parent/folder/childfolder4/
                                  /pathto/parent/folder/childfolder5/
                                  /pathto/parent/folder/childfolder6/
                                  /pathto/parent/folder/childfolder7/
                                  /pathto/parent/folder/childfolder8/
                                  

                                  【讨论】:

                                    【解决方案27】:

                                    这是我用来仅列出目录名称的内容:

                                    ls -1d /some/folder/*/ | awk -F "/" "{print \$(NF-1)}"
                                    

                                    【讨论】:

                                      【解决方案28】:

                                      如果您的文件夹名称中有空间 $9 打印将不起作用,请尝试以下命令

                                      ls -l yourfolder/alldata/ | grep '^d' | awk '{print $9" " $10}'
                                      

                                      输出

                                      ls -l yourfolder/alldata/ | grep '^d' | awk '{print $9" " $10}'
                                      testing_Data 
                                      Folder 1
                                      

                                      【讨论】:

                                        猜你喜欢
                                        • 2019-06-03
                                        • 2013-03-14
                                        • 1970-01-01
                                        • 2011-07-07
                                        • 1970-01-01
                                        • 2010-11-04
                                        • 2010-11-03
                                        • 2016-06-18
                                        • 1970-01-01
                                        相关资源
                                        最近更新 更多