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


952

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

模式到底是*/做什么的?

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


7
请参阅对此答案的编辑unix.stackexchange.com/a/75047/32647解释-d实际含义。
Evgeni Sergeev

Answers:


989

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


87
请注意,*/它将不与任何隐藏的文件夹匹配。要包括它们,或者像一样明确指定它们ls -d .*/ */,或者在Bash中设置dotglob选项
Gergő

1
@ytpillai发生这种情况是因为没有要列出的子目录。任何时候使用ls不存在的东西,都会收到该错误。
Gordon Davisson

1
好的,谢谢,我刚才检查了一下,结果发现唯一的目录是根文件夹。
ytpillai 2015年

1
@GordonDavisson可以使用bash选项避免失败的消息shopt -s nullglob

4
@BinaryZebra设置nullglob可以避免出现错误消息,但会引起更多的混乱:设置了nullglob且没有子目录时,ls */将扩展为just ls,它将列出当前目录中的所有文件。我很确定那不是您想要的那种情况。
戈登·戴维森

481

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

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/

2
注意 3对我来说明显比其他人慢。在我测试的目录中:1.012s,2.016s,3 .055s4.021s。
同构

@isomorphismes,您如何测量时间?怎么做?顺便说一句,我必须说,编号1是我的最爱。
艾伯特

Albert,我使用time了Unix函数。///我同意,echo */比聪明ls -d */
同构

9
您应该注意两件小事。ls -l | grep“ ^ d”过滤掉目录的符号链接,而'ls -d * /'显示它们。另外,如果目标目录中根本没有目录,则“ ls -d * /”也会失败。
Zoran Pavlovic 2014年

15
1.在处理带有空格的文件夹名称时,该选项将引起很多麻烦。
Shrikant Sharat 2014年

99

我用:

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

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

我的两分钱。


18
-1选项ls也将以单列格式输出ls -1 -d */
卡林2014年

3
@ user29020应该注意,-1对于每个条目,仍然输出尾部斜杠。
丹尼斯

将其添加.bashrc为别名时,如何添加'/'
RNA

@RNA回答迟了,但对未来的人:尝试用反斜杠转义?'\/'
Caek 2015年

1
如果有斜杠,则中断。这仅会删除斜杠:| sed -e 's-/$--'
Victor Sergienko,

62

对于所有不包含子文件夹的文件夹:

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

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

find /home/alice/Documents -type d

2
为了匹配该问题(但包括点文件),第一个应该是:find /home/alice/Documents -maxdepth 1 -mindepth 1 -type d否则,您将/home/alice/Documents自身包括在内。要包括指向目录的符号链接,请在-L
-19个

这似乎是最明智的解决方案,因为find是为此任务实际使用的工具。您可以通过管道传输到grep -v'^ \ ./$'来排除第一个结果-./对于当前目录
-Siliconrockstar

38

4(更多)可靠的选项。

一个不带引号的星号*将被解释为通过所述壳的图案(水珠)。
外壳程序将在路径名扩展中使用它。
然后,它将生成与模式匹配的文件名列表。
一个简单的星号将匹配PWD(当前工作目录)中的所有文件名。
更复杂的模式,*/将匹配以结尾的所有文件名/
因此,所有目录。这就是为什么命令:

1.-回声。

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

将被外壳扩展到echoPWD中的所有目录。


要对此进行测试,请执行以下操作:创建一个mkdir名为test-dir 的目录(),并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中目录列表的原因。使它的-d选项ls列出当前目录条目,而不是每个目录的内容(默认情况下显示)。

ls -d */

但是,此命令(某种程度上)不太可靠。上面列出的奇数命名文件将失败。它会用几个名字cho住。您需要一个一个地擦除,直到找到有问题的。

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

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


我认为您应该将“安全”一词替换为“可靠”。您的文章让我觉得其他的解决方案是“不安全”(脆弱或利用。)
阿马多·马丁内斯

1
@AmadoMartinez做一个一般的s / safe / reliable /。更好?

21

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

男人树可以看到更多的论点


15

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

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

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

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

\ ls -d * /


11

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

alias lsd='ls -ld */'

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


你不能只用吗?ls -l路径| grep dr
jrobertsz66 '16

5
“然后,lsd将产生所需的结果。” 我笑了
fbafelipe

1
以我的经验,它会产生结果。
Todd

我使用“ lad”(列出所有目录),并且我还使用了“。* /”来包括隐藏目录。当然,影射也不对我失去。
DryLabRebel,

11

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

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

不包括符号链接

给出了一种使用的解决方案ls,但它与其他解决方案有所不同,因为它排除了指向目录的符号链接

ls -l | grep '^d'

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

包括符号链接

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

ls -1p | grep '/$'

或者,摆脱尾随的斜杠:

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

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

注意:如果我们要使用斜杠,但不希望使用突出显示斜线,则grep可以通过将行的实际匹配部分留空来暗中删除突出显示:

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

9

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

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,请看看这个答案
PHP学习者

与其他答案相比,“ ls .. | grep ... | awk”的第一个选项似乎脚本过多。
拉尔斯·诺丁

1
您假设目录名称中没有空格。
本杰明·R

7

显示不带文件夹的列表 /

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

2
ls -d1 */ | tr -d "/"
ccpizza

无需调用外部命令:set -- */; printf "%s\n" "${@%/}"

我喜欢@wholanda的解决方案。我的简短解决方案是(经测试且可行):ls -d * / | sed's | / ||
g'– klor

还有一个lsdir别名也很有用:alias lsdirs =“ ls -d * / | sed's | / || g'”
klor



4

使用以下命令测试项目是否为目录test -d

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

1
请解释该代码的作用以及与问题的关系。
Ken YN

1
它运行命令'ls',然后循环进行输出测试-如果每个目录都是目录,则回显-如果
可行,

3

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

仅列出目录,我喜欢此功能:

# 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'
}

3

仅供参考,如果您要多行打印所有文件,可以执行一个操作ls -1,该命令将在单独的行中打印每个文件。file1 file2 file3


3

当前目录的简单列表是:

ls -1d ./*/

您想要它分类和清洁吗?

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

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


3

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

ls -ltr | grep drw

4
ls -l | grep '^d' | awk '{print $9}'
dw1

2

一线式仅从“这里”列出目录。

随着文件数。

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

2

我部分解决了:

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

好吧,这减少了我,市长的一部分:)


2

再加上使它变成一个完整的圆圈,以检索每个文件夹的路径,请使用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/


1

这是我仅用于列出目录名称的方法:

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

1

回答最初的问题,*/ls本质无关。它是由Shell / Bash在称为globlob的过程中完成的。

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


1

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

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

或用awk

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

但是,这可能会更好,并将保留/之后的目录名称。

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

这看起来像韩文!
Paschalis

0
file *|grep directory

O / P(在我的机器上)-

[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

0

有史以来最短的命令(实际上是hack),仅列出目录。输入感兴趣目录的绝对路径或相对路径,然后按Enter键进入感兴趣目录。现在,键入cd并按Tab键。现在仅显示目录。

user@ubuntu:~/Desktop$cd <tab key>

上面的命令现在应该只显示Desktop中的文件夹。确实最短。


这假定启用了自动补全功能,并且可能无法在所有情况下都起作用。另外,如果您想使用此方法执行某些操作(例如,将输出通过管道传递到某些内容中),它将无法正常工作。但是对于仅查看输出,请确保它可以快速简便地工作。
lacostenycoder,

完善!我删除了“。” 然后它起作用了
user2060451
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.