在Bash中只列出使用ls的目录?

此命令列出当前路径中的目录:

ls -d */

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

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

1121987 次浏览

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

有四种方法可以做到这一点,每种方法都有不同的输出格式

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 csdrwxr-xr-x   6 h  staff     204 Jun  8 10:55 draftdrwxr-xr-x   9 h  staff     306 Jun  8 10:55 filesdrwxr-xr-x   2 h  staff      68 Jun  9 13:19 hacksdrwxr-xr-x   6 h  staff     204 Jun  8 10:55 mastersdrwxr-xr-x   4 h  staff     136 Jun  8 10:55 static

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

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

csdraftfileshacksmastersstatic

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

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

我使用:

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

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

我部分解决了它:

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 directoryln: «/home/inukaze/../..»: can't overwrite a directoryln: accesing to «/home/inukaze/.config»: too much symbolics links levelsln: accesing to «/home/inukaze/.disruptive»: too much symbolics links levelsln: accesing to «/home/inukaze/innovations»: too much symbolics links levelsln: accesing to «/home/inukaze/sarl»: too much symbolics links levelsln: accesing to «/home/inukaze/.e_old»: too much symbolics links levelsln: accesing to «/home/inukaze/.gnome2_private»: too much symbolics links levelsln: accesing to «/home/inukaze/.gvfs»: too much symbolics links levelsln: accesing to «/home/inukaze/.kde»: too much symbolics links levelsln: accesing to «/home/inukaze/.local»: too much symbolics links levelsln: accesing to «/home/inukaze/.xVideoServiceThief»: too much symbolics links levels

好吧,这减少了我,主要部分:)

仅从“此处”列出目录的单行程序。

与文件计数。

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

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

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

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

find /home/alice/Documents -type d

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

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

添加以使其完整循环,以检索每个文件夹的路径,使用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/

这是我用的

ls -d1 /Directory/Path/*;

*/是一个文件名匹配模式,用于匹配当前目录中的目录。

为了只列出目录,我喜欢这个函数:

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

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

使用示例:

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

注意:如果您使用-i选项,它会中断。这是一个修复:

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

#0命令在这里也非常有用。默认情况下,它将显示所有文件和目录的完整深度,并使用一些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

更多参数可以在#0中看到。

四个(更多)可靠的选择。

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

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

1.-回声。

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

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


要测试这一点:创建一个名为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仍然是扩展文件名列表的原因。shell是在PWD中获取目录列表的原因。ls-d选项使其列出当前目录条目而不是每个目录的内容(默认显示)。

ls -d */

但是,此命令(有些)不太可靠。它会因上面列出的奇怪命名文件而失败。它会被多个名称阻塞。您需要一个接一个地擦除,直到找到有问题的文件。

2.-ls

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

ls -d ./*/                     ### More reliable BSD lsls -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)。
  • 名称中的每个换行符都将启动一个新的回显命令。

4.-功能

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

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

呈现此列表:

---*csdir with spacesdraftfiles-hmasters-nstatic-v var

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

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

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

仅供参考,如果您想以多行方式打印所有文件,您可以执行ls -1,这将在单独的行中打印每个文件。file1file2file3

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

alias lsd='ls -ld */'

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

如果你想知道为什么'ls-d*/'的输出会给你两个尾随斜杠,比如:

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

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

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

\ls -d */

实际的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 '(?=/$)'

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

for i in $(ls); do test -d $i && echo $i ; done
file * | grep directory

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

[root@rhel6 ~]# file * | grep directorymongo-example-master:    directorynostarch:                directoryscriptzz:                directorysplunk:                  directorytestdir:                 directory

上面的输出可以通过使用削减来进一步细化:

file * | grep directory | cut -d':' -f1mongo-example-masternostarchscriptzzsplunktestdir
* could be replaced with any path that's permittedfile - determine file typegrep - searches for string named directory-d - to specify a field delimiter-f1 - denotes field 1

使用Perl:

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

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

ls -ltr | grep drw

对于仅列出目录

ls -l | grep ^d

对于仅列出文件

ls -l | grep -v ^d

或者你也可以这样做:

ls -ld */

以下是我仅用于列出目录名称的内容:

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

要回答最初的问题,*/本身与ls无关;它是由shell/Bash在称为全球化的过程中完成的。

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

当前目录的普通列表,它将是:

ls -1d */

如果你想把它清理干净:

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

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

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

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

或者用awk

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

然而,这可能更好,并且将在目录名之后保留/

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

如果你有空间在您的文件夹名称9美元打印不会工作尝试下面的命令

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

输出

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

ls和awk(不带grep)

不需要使用grep,因为awk可以执行常规的xpress检查,所以这样做就足够了:

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

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

非常简单和干净

我发现这个解决方案最舒服,我添加到列表中:

find * -maxdepth 0 -type d

不同之处在于它开头没有./,文件夹名称可以随时使用。