仅列出当前目录中的常规文件(但不列出目录)


126

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

find . -maxdepth 1 -type f

或统计

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

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


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

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

Answers:


32

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

echo *(.)

只会返回常规文件列表,也可能会返回错误,具体取决于您的配置。

对于非目录:

echo *(^/)

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

echo *(-.)

用于常规文件和指向常规文件的符号链接。

echo *(-^/)

用于非目录,也没有指向目录的符号链接。

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


170
ls -p | grep -v / 

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

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


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

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

3
如果您还希望排除指向目录do的符号链接ls -pL | grep -v /。添加的-L取消引用符号链接。
马提亚斯·布劳恩

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

如果您想获取所有不带文件夹的文件,只需删除-v
jasonleonhard

23

仅列出常规文件:

ls -al | grep '^-'

包含(到任何类型的文件的)符号链接:

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

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

Debian / Ubuntu

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

run-parts --list --regex . .

使用绝对路径:

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

打印/etcp结尾的所有文件的名称d

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

15

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
Totor 2014年

8
bash-4.2$ ls -F | grep -v '[/@=|]$' | more

ls的-F选项将*附加到可执行文件,/附加到目录,@附加到符号链接,=附加到套接字和| 到FIFO。然后,您可以使用grep从输出中排除非常规文件字符,您便拥有了文件。这将在任何shell中都有效,而不仅仅是zsh。

缺点是:

  1. 任何文件,其名称结尾的@=|将被排除在外(但你不应该真的有在名称中的字符的文件反正)
  2. 这并不排除设备文件或某些系统(如门)上某些奇特类型的文件。
  3. 您将在任何可执行文件上附加一个星号。这可以通过管道处理sed来解决,以从输出中删除任何“ *”字符。
  4. 如果文件名包含换行符,则无法正常工作。

在系统上我写这篇文章时,文件的10%都包含姓名=@|字符。=在具有base64或带引号的可编码部分的maildir或文件名中很常见。@在区域设置中,用于电子邮件地址等。但是,它们很少出现在文件名的末尾。(只有31出220万这个系统上的实例)
斯特凡Chazelas

3

手册指出,“ 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)

0

这不是特别短,但是如果需要快速调用它,可以将其转换为脚本或别名。使用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


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.