在 Bash 中使用 ls 仅列出目录?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14352290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:12:58  来源:igfitidea点击:

Listing only directories using ls in Bash?

bashdirectoryls

提问by Sibi

This command lists directories in the current path: ls -d */

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

What exactly does the pattern */do?

模式究竟有*/什么作用?

And how can we give the absolute path in the above command (e.g. ls -d /home/alice/Documents) for listing only directories in that path?

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

回答by Gordon Davisson

*/is a pattern that matches all of the subdirectories in the current directory (*would match all files andsubdirectories; the /restricts it to directories). Similarly, to list all subdirectories under /home/alice/Documents, use ls -d /home/alice/Documents/*/

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

回答by Albert

Four ways to get this done, each with a different output format

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

1. Using echo

1. 使用 echo

Example: echo */, echo */*/
Here is what I got:

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

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

2. Using lsonly

2.ls仅使用

Example: ls -d */
Here is exactly what I got:

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

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

Or as list (with detail info): ls -dl */

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

3. Using lsand grep

3. 使用lsgrep

Example: ls -l | grep "^d"Here is what I got:

示例: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 Script (Not recommended for filename containing spaces)

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

Example: for i in $(ls -d */); do echo ${i%%/}; done
Here is what I got:

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

cs  
draft  
files  
hacks  
masters  
static

If you like to have '/' as ending character, the command will be: for i in $(ls -d */); do echo ${i}; done

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

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

回答by Thomas Altfather Good

I use:

我用:

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

This creates a single column with no trailing slash - useful in scripts.

这将创建一个没有尾部斜杠的单列 - 在脚本中很有用。

My two cents.

我的两分钱。

回答by at3m

For all folders withoutsubfolders:

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

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

For all folders withsubfolders:

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

find /home/alice/Documents -type d

回答by at3m

4 (more) Reliable Options.

4 个(更多)可靠选项。

An unquotedasterisk *will be interpreted as a pattern (glob) by the shell.
The shell will use it in pathname expansion.
It will then generate a list of filenames that match the pattern.
A simple asterisk will match all filenames in the PWD (present working directory).
A more complex pattern as */will match all filenames that end in /.
Thus, all directories. That is why the command:

不带引号的星号*将被 shell 解释为模式(glob)。
shell 将在路径名扩展中使用它。
然后它将生成与模式匹配的文件名列表。
一个简单的星号将匹配 PWD(当前工作目录)中的所有文件名。
更复杂的模式 as*/将匹配所有以/.
因此,所有目录。这就是为什么命令:

1.- echo.

1.- 回声。

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

will be expanded (by the shell) to echoall directories in the PWD.

将(由外壳程序)扩展到echoPWD 中的所有目录。



To test this: Create a directory (mkdir) named like test-dir, and cdinto it:

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

mkdir test-dir; cd test-dir

Create some directories:

创建一些目录:

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:


The command echo ./*/will remain reliable even with odd named files:

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

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

But the spaces in filenames make reading a bit confusing.

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



If instead of echo, we use ls, the shell is still what is expanding the list of filenames. The shell is the reason to get a list of directories in the PWD. The -doption to lsmakes it list the present directory entry instead of the contents of each directory (as presented by default).

如果echo我们使用代替,lsshell 仍然是扩展文件名列表的内容。shell 是获取 PWD 中目录列表的原因。该-d选项ls使得它列出当前目录条目,而不是每个目录的内容(如默认提交)。

ls -d */

However, this command is (somewhat) less reliable. It will fail with the odd named files listed above. It will choke with several names. You need to erase one by one till you find the ones with problems.

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

2.- ls

2.- ls

The GNU lswill accept the "end of options" (--) key.

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

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

3.-printf

3.-printf

To list each directory in its own line (in one column, similar to ls -1), use:

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

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

And, even better, we could remove the trailing /:

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

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

An attempt like this:

像这样的尝试:

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

Will fail on:

将失败:

  • some names (ls -d */) as already shown above.
  • will be affected by the value of IFS.
  • will split names on spaces and tabs (with default IFS).
  • each newline in the name will start a new echo command.
  • 一些名称 ( ls -d */) 如上所示。
  • 的值会受到影响IFS
  • 将在空格和制表符上拆分名称(默认为IFS)。
  • 名称中的每个换行符都将启动一个新的 echo 命令。

4.- Function

4.- 功能

Finally, using the argument list inside a function will not affect the arguments list of the present running shell. Simply:

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

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

presents this list:

介绍这个列表:

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

This options are safe with several types of odd filenames.

此选项对于多种类型的奇数文件名是安全的。

回答by Hamish Downer

The treecommand is also pretty useful here. By default it will show all files and directories to a complete depth, with some ascii characters showing the directory tree.

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

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

But if we wanted to get just the directories, without the ascii tree, and with the full path from the current directory, you could do:

但是,如果我们只想获取目录,而没有 ascii 树,并且想要获取当前目录的完整路径,则可以执行以下操作:

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

The arguments being:

论据是:

-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.

And if you then want the absolute path, you could start by specifying the full path to the current directory:

如果您想要绝对路径,您可以首先指定当前目录的完整路径:

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

And to limit the number of subdirectories, you can set the max level of subdirectories with -L level, eg:

并且要限制子目录的数量,您可以使用 设置子目录的最大级别-L level,例如:

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

More arguments can be seen with man tree

man tree可以看到更多参数

回答by gwideman

In case you're wondering why output from 'ls -d */' gives you twotrailing slashes, like:

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

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

it's probably because somewhere your shell or session config files alias the ls command to a version of ls that includes the -F flag. That flag appends a character to each output name (that's not a plain file) indicating the kind of thing it is. So one slash is the from matching the pattern '*/', and the other slash is the appended type indicator.

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

To get rid of this issue, you could of course define a different alias for ls. However, to temporarily not invoke the alias, you can prepend the command with backslash:

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

\ls -d */

\ls -d */

回答by pyrocrasty

Actual lssolution, including symlinks to directories

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

Many answers here don't actually use ls(or only use it in the trivial sense of ls -d, while using wildcards for the actual subdirectory matching. A true lssolution is useful, since it allows the use of lsoptions for sorting order, etc.

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

Excluding symlinks

排除符号链接

One solution using lshas been given, but it does something different from the other solutions in that it excludes symlinksto directories:

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

ls -l | grep '^d'

(possibly piping through sedor awkto isolate the file names)

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

Including symlinks

包括符号链接

In the (probably more common) case that symlinks to directories should be included, we can use the -poption of ls, which makes it append a slash character to names of directories (including symlinked ones):

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

ls -1p | grep '/$'

or, getting rid of the trailing slashes:

或者,去掉尾部的斜杠:

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

We can add options to lsas needed (if a long listing is used, the -1is no longer required).

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

note:if we wanttrailing slashes, but don't want them highlighted by grep, we can hackishly remove the highlighting by making the actual matched portion of the line empty:

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

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

回答by guesty guesterson

I just add this to my .bashrcfile (you could also just type it on the command line if you only need/want it for one session)

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

alias lsd='ls -ld */'

then lsd will produce the desired result.

然后 lsd 将产生所需的结果。

回答by PHP Learner

If hidden directory is not needed to be listed, I offer:

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

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

And if hidden directories is needed to be listed, use:

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

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

OR

或者

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