我可以使用ls -ld */列出当前目录中的所有目录条目。是否有类似的简单方法仅列出当前目录中的所有常规文件?我知道我可以使用find

find . -maxdepth 1 -type f


或stat

stat -c "%F %n" * | grep "regular file" | cut -d' ' -f 3-


,但是这些并不能使我感到震惊过于优雅。是否有一种很好的简短方法仅列出常规文件(我不在乎设备,管道等),而不列出当前目录的子目录?列出符号链接也将是一个加号,但不是必须的。

评论

“过分优雅”是什么意思?据我所知,find命令是执行所需操作的最佳方法。对于一些可靠的其他选项,您应该研究特定于shell的命令(这些命令不是可移植的)!

@rahmu我使用的是类似于ls -d * /的东西,它简短,易于键入且易于理解。因此,即使我不使用zsh,我也对Ulrich Dangel的回答感到非常满意。

相似:在Ubuntu SE上列出目录中的文件,但不列出该目录中的子目录及其内容

#1 楼

使用zsh和Glob限定词,您可以轻松地直接表达它,例如:

echo *(.)


将仅返回常规文件列表或错误,具体取决于您的配置。

对于非目录:

echo *(^/)


(将包括符号链接(包括目录),命名管道,设备,插座,门... )

echo *(-.)


用于常规文件和符号链接到常规文件。

echo *(-^/)


用于非目录,没有也可以通过符号链接到目录。

此外,如果要包括Dot文件(隐藏文件)(例如D),请参阅*(D-.) globlob限定符。

#2 楼

ls -p | grep -v / 


此命令列出了所有不是目录的非隐藏文件(常规文件,链接,设备文件等)。要还包括隐藏文件,请将-A选项添加到ls

假定没有文件名中包含换行符。在-q上添加ls选项会将包括换行符在内的所有不可打印字符转换为?,确保它们在一行上,因此适合馈送至基于行的实用程序(例如grep)并在终端上打印。

评论


+1,这是一个很好的答案。对没有评论的新用户投反对票使我感到震惊,尤其是在提供有效答案的情况下。我可以看到的唯一例外情况是文件名中是否包含换行符。如果支持,还可以保留颜色。对于GNU,您可以在ls中添加--color = always,对于OSX -G。

– Graeme
2014年2月23日在10:38

嗨,您提供的命令很棒,它肯定会对我有所帮助,但是我想知道是否可以同时使用上述命令并更改文件许可权?我尝试在末尾添加sudo chmod 777,但出现错误...非常感谢您的帮助

– Dissidia
2015年9月4日在2:14

如果您还想排除指向目录的符号链接,请使用ls -pL | grep -v /。添加的-L取消引用符号链接。

–马特西亚斯·布劳恩(Matthias Braun)
16 Mar 7 '16 at 18:36

如果您还喜欢使用通配符过滤器,请执行ls -pdL命令* | grep -v /。添加的-d选项列出目录本身,而不是目录内容,因此将被正确排除。

– Rockallite
17年1月24日,2:15



我特别喜欢“ ls -p | grep -v /”,因为我可以修改为“ ls -latrp | grep -v /”以获取按时间排序的全貌。谢谢!

– opinion_no9
19/12/15在12:18

#3 楼

仅列出常规文件:

ls -al | grep '^-'


包括符号链接(指向任何类型的文件):

ls -al | grep '^[-l]'


列表的第一个字符描述文件的类型,因此-表示它是常规文件,符号链接为l

Debian / Ubuntu

打印所有匹配文件的名称(包括链接):

run-parts --list --regex . .


绝对路径:

run-parts --list --regex . "$PWD"


打印/etc中所有以p开头并以d结尾的文件的名称:

run-parts --list --regex '^p.*d$' /etc


评论


这是考虑链接和FIFO的唯一正确答案。方式被低估了。

–卡米尔·库尔兹诺夫斯基(Kamil Kurzynowski)
20年8月8日在20:36

#4 楼

ls没有这样做的选择,但是关于unix和linux的好处之一是,冗长而笨拙的管道可以轻松地转换成shell脚本,函数或别名。并且它们可以像其他任何程序一样在管道中使用。

(注意:函数和别名存在一些范围问题。脚本可用于任何可执行文件,这些可执行文件可以读取和执行它们别名和功能仅在当前外壳中可用-尽管子外壳的.profile / .bashrc等可能会重新定义它们并使其可用。此外,脚本可以用任何语言编写-包括bash / sh,awk, perl,python和其他工具-无论是最适合您的工作还是您最熟悉的工具)

例如

alias lsf='find . -maxdepth 1 -type f -print0 | xargs -0r ls'添加了xargs,以便您可以使用所有常用的ls选项,例如lsf -lrS

因为使用了find,所以将显示所有通常隐藏的点文件,并且所有文件名都将带有前缀./-这是您会注意到的唯一区别。

您可以使用! -iname '.*'排除点文件,但随后必须具有两种版本的别名-一个显示点文件,另一个不显示。

alias lsf2='find . -maxdepth 1 -type f -a ! -iname '\''.*'\'' -print0 | xargs -0r ls'

或者,如果lsf是脚本而不是别名,则可以解析选项(也许使用getopts或/ usr / bin / getopt或类似文件),并排除点文件,除非存在-a

评论


-name足够,您不需要-iname。

– Tortor
2014年1月2日,1:13

#5 楼

bash-4.2$ ls -F | grep -v '[/@=|]$' | more
ls的-F选项将*附加*到可执行文件,/附加到目录,@附加到符号链接,=附加到套接字以及|到FIFO。然后,您可以使用grep从输出中排除非常规文件字符,您便拥有了文件。这适用于所有shell,不仅限于zsh。

弱点是:


@=|结尾的任何文件都将被排除(但您实际上不应该使用名称中带有这些字符的文件)
这并不排除设备文件或某些系统(如门)上某些奇特类型的文件。
您将在其后附加一个星号任何可执行文件。可以通过对sed进行管道传递来删除输出中的所有“ *”字符来解决。
如果文件名中包含换行符,则无法正常工作。


评论


在我正在写的系统上,有10%的文件名包含=,@或|字符。在具有base64或带引号的可编码部分的maildir或文件名中,=是常见的。 @在语言环境定义中,用于电子邮件地址等。但是,它们很少出现在文件名的末尾。 (例如,在此系统上,220万中只有31)

–StéphaneChazelas
16年7月31日在15:14

#6 楼

手册指出,“ f”选项仅针对“常规文件”,而不针对管道,套接字或块/字符设备,这意味着您已经在执行正确的操作。

   -type c
          File is of type c:

          b      block (buffered) special

          c      character (unbuffered) special

          d      directory

          p      named pipe (FIFO)

          f      regular file

          l      symbolic link; this is never true if the -L option or the
                 -follow option is in effect, unless the symbolic link  is
                 broken.  If you want to search for symbolic links when -L
                 is in effect, use -xtype.

          s      socket

          D      door (Solaris)


#7 楼

我最喜欢的解决方案:
#!/bin/bash
for f in *
do
        if [ -f $f ]; then echo "$f"; fi
done

它可以作为一个衬里完成:
for f in *; do [ -f $f ] && echo "$f"; done;可以在子shell中运行它,并将其cd转到目标目录。我将ls用于包含大量文件的目录,因为它比在这种情况下查找要快(在我看来,这更加优雅)。理想情况下,您可以使用printf而不是echo来获得最大的安全性。

评论


触摸“ x -o -v a [$(reboot)]”后,尝试。请参阅忘记在bash / POSIX shell中引用变量的安全隐患。另请参见为什么printf比echo好?

–StéphaneChazelas
20年8月9日在16:58

有趣的是,您提到了这一点,但是除了未列出'x -o -v a [$ reboot]'之外,什么都没有发生。我可以引用该变量以提高安全性或使用printf。

–卡米尔·库尔兹诺夫斯基(Kamil Kurzynowski)
20年8月10日在5:56

#8 楼

这不是特别短,但是如果需要快速调用它,可以将其转换为脚本或别名。使用ls命令作为输入数组,在通过管道传递给grep的每个条目上调用ls -ld,以排除输出发送为null的目录,如果成功,则回显原始输入:

for list in `ls` ; do ls -ld $list | grep -v ^d > /dev/null && echo $list ; done ;


您可以反转grep和条件输出,结果相同:

for list in `ls` ; do ls -ld $list | grep ^d > /dev/null || echo $list ; done ;


评论


\ dev \ null?!?!

–manatwork
13-10-7在9:07

相关:unix.stackexchange.com/questions/128985/why-not-parse-ls

– Kusalananda♦
18年7月27日在21:26

#9 楼

这是一个有点旧的线程,但是仅列出文件的最简洁的方法。

ls -al | grep '^-' | awk '{print }'


评论


相关:unix.stackexchange.com/questions/128985/why-not-parse-ls

– Kusalananda♦
18年7月27日在21:25

触摸“某些文件名”以查看快速的反例

– Jeff Schaller♦
18年7月28日在0:46

@JeffSchaller您的观点正确。对于这样的事情。 ls -al | grep'^-'| awk'{for(i = 9; i <= NF; ++ i)printf $ i“” FS;打印“”}',应处理其中带有空格的文件。

– R J
18年7月28日在10:34



@RJ,如果它们是前导或尾随空格,或者有一个或多个空格的序列,则不然。 TAB和NL也将是一个问题,因为您传递的文件名部分是printf的format参数,所以%也将是一个问题。

–StéphaneChazelas
20年8月9日在17:01