该命令列出当前路径下的目录:
ls -d */
模式*/到底做什么?
我们如何在上面的命令中给出绝对路径(例如ls -d /home/alice/Documents),只列出该路径下的目录?
该命令列出当前路径下的目录:
ls -d */
模式*/到底做什么?
我们如何在上面的命令中给出绝对路径(例如ls -d /home/alice/Documents),只列出该路径下的目录?
当前回答
回答最初的问题,*/和ls本身没有关系;它是由shell/Bash完成的,这个过程被称为globbing。
这就是为什么echo */和ls -d */输出相同的元素。(-d标志使ls输出目录名,而不是目录内容。)
其他回答
*/是一个匹配当前目录中所有子目录的模式(*将匹配所有文件和子目录;/将其限制为目录)。类似地,要列出/home/alice/Documents下的所有子目录,请使用ls -d /home/alice/Documents/*/
对于所有没有子文件夹的文件夹:
find /home/alice/Documents -maxdepth 1 -type d
对于所有带子文件夹的文件夹:
find /home/alice/Documents -type d
仅列出目录:
ls -l | grep ^d
只列出文件:
ls -l | grep -v ^d
或者你也可以这样做:
ls -ld */
实际的ls解决方案,包括到目录的符号链接
这里的许多答案实际上并不使用ls(或者仅在ls -d的普通意义上使用它,而使用通配符进行实际的子目录匹配。一个真正的ls解决方案是有用的,因为它允许使用ls选项来排序顺序等。
不包括符号链接
已经给出了一个使用ls的解决方案,但它与其他解决方案不同,因为它排除了到目录的符号链接:
ls -l | grep '^d'
(可能通过sed或awk管道来隔离文件名)
包括符号链接
在应该包含到目录的符号链接的情况下(可能更常见),我们可以使用ls的-p选项,这使得它在目录名(包括符号链接的目录名)后面附加一个斜杠字符:
ls -1p | grep '/$'
或者,去掉后面的斜杠:
ls -1p | grep '/$' | sed 's/\/$//'
我们可以根据需要向ls添加选项(如果使用长列表,则不再需要-1)。
注意:如果我们想要后面的斜杠,但不希望它们被grep高亮显示,我们可以通过将实际匹配的部分设为空来删除高亮显示:
ls -1p | grep -P '(?=/$)'
四种(更多)可靠的选择。
不加引号的星号*将被shell解释为模式(glob)。shell将在路径名展开中使用它。然后它将生成一个与模式匹配的文件名列表。
一个简单的星号将匹配PWD(当前工作目录)中的所有文件名。更复杂的*/模式将匹配所有以/结尾的文件名。因此,所有目录。这就是为什么命令:
1.——回声。
echo */
echo ./*/ ### Avoid misinterpreting filenames like "-e dir"
将被扩展(由shell)以回显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/
但是文件名中的空格让阅读有点混乱。
如果我们用ls代替echo。shell仍然是扩展文件名列表的对象。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
对于几种类型的奇数文件名,这些选项是安全的。