如何在Bash中仅列出目录中的文件而不是目录?

154

如何列出一个文件夹下的所有文件但不包括它们的文件夹或子文件。换句话说: 如何只列出文件?


14个回答

214

使用find

find . -maxdepth 1 -type f

使用 -maxdepth 1 选项确保只在当前目录中查找(或者,如果你用某个路径替换 . ,那就是该目录)。如果你想要完整递归地列出该目录及其子目录中的所有文件,只需删除该选项。


在评论了mklement0的答案后,我意识到“find ./*.png -maxdepth 1 -type f > pngs.txt”可能会达到同样的效果。它确实可以做到这一点,而无需安装脚本。 - Alex Hall
2
在Mac上,find命令没有-type-maxdepth选项。 - Timofey
2
@Tim:-type-maxdepth不是普通意义上的选项;BSD find(在OS X上使用)将它们称为“primaries”,并且它们必须出现在文件名操作数(在本例中为.;请注意,与Linux不同,BSD版本需要至少一个显式文件名操作数)之后;此答案中的命令在Mac上绝对可行。 - mklement0
1
@AlexHall: 这是一个巧妙的解决方案(虽然我建议使用 find *.png -maxdepth 0 -type f 来避免输出文件名中的 ./ 前缀;还要注意 -maxdepth0,不是 1),只要你需要在 字母顺序 中获取文件名。如果您想要 ls 可以为您完成的其他操作(不同的输出格式/排序,内联控件是否包括隐藏项等),并补充 [多重] 类型过滤,则我的答案中的脚本可以帮助到您。 - mklement0
2
与答案中的 find . -maxdepth 1 -type f 相比,find * -maxdepth 0 -type f(源自 @AlexHall 的评论)有以下不同之处: find . ... 命令总是包括隐藏文件,并在输出文件名时加上 ./ 前缀。而且,在 GNU find(Linux)中,通常会输出未排序的列表。 find * ... 命令则由于让 shell 在前面执行 globbing,因此默认情况下排除隐藏项目(可以使用 shopt -s dotglob 更改),仅输出文件名(无前缀),按字母顺序排序。 两种方法都不包括对文件的符号链接;使用 -L 选项即可包括符号链接。 - mklement0
@Tim 是的,基本上是因为它不是POSIX:http://pubs.opengroup.org/onlinepubs/009695399/utilities/find.html ls -p | grep -v 是的:https://dev59.com/2Wkv5IYBdhLWcg3wdQrm#46135507 - Ciro Santilli OurBigBook.com

39
ls -p | grep -v /

使用 ls -p 命令可以在文件夹名称后显示 / 斜杠,作为您删除文件夹的标记。


1
很高兴看到一个例子同时使用了lsfind,因为后者返回相对路径而前者仅返回文件名。用正确的工具做好工作。 - Ben Amos

9
  • carlpett的基于find的答案find . -maxdepth 1 -type f)原则上可行,但与使用ls不完全相同:您会得到一个可能未排序的文件名列表,所有文件名都以./为前缀,并且您失去了应用ls的许多选项的能力;
    此外,find 总是找到隐藏项目,而ls的行为取决于是否存在-a-A选项。

    • Alex Hall在问题的评论中提出的一个改进方法是将shell globbingfind结合使用

       find * -maxdepth 0 -type f  # find -L * ... includes symlinks to files
      
      • 然而,虽然这个方法解决了前缀问题并给出了按字母顺序排序的输出,但您仍然无法(内联)控制包含隐藏项目的情况,也无法访问ls的许多其他排序/输出格式选项。
  • Hans Roggeman的ls+grep答案是实用的,但将您锁定为使用长(-l)输出格式


为了解决这些限制,我编写了flsfiltering ls)实用程序
  • 该实用程序提供了ls的输出灵活性,同时还提供了类型过滤功能
  • 只需在ls参数列表之前放置类型过滤字符,例如f表示文件,d表示目录,l表示符号链接(运行fls --helpfls --man以了解更多信息)。

示例:

fls f        # list all files in current dir.
fls d -tA ~  #  list dirs. in home dir., including hidden ones, most recent first
fls f^l /usr/local/bin/c* # List matches that are files, but not (^) symlinks (l)

安装

支持的平台

  • npm注册表安装时: LinuxmacOS
  • 手动安装时:任何带有Bash类Unix平台

npm注册表

注意:即使您不使用Node.js,其软件包管理器npm也可以跨平台工作,并且易于安装;尝试
curl -L https://git.io/n-install | bash

安装Node.js后,请按以下方式安装:

[sudo] npm install fls -g

注意:

  • 您是否需要使用sudo取决于您如何安装Node.js/io.js以及是否稍后更改了权限; 如果出现EACCES错误,请尝试使用sudo再次运行。

  • -g确保全局安装,并且需要将fls放入系统的$PATH中。

手动安装

  • 下载this bash脚本并将其命名为fls
  • 使用chmod +x fls命令使其可执行。
  • 将其移动或创建符号链接到您的$PATH文件夹中,例如/usr/local/bin(macOS)或/usr/bin(Linux)。

1
太棒了。即使需要创建另一个脚本也没问题。我从你提供的纯文本源链接中复制粘贴到一个文本文件中,并在Cygwin中使用以下命令运行它:fls.sh f *.png > pngs.txt然后,哇:一个没有路径的.png文件列表。但是,真的没有类似于DOS的“dir /b”开关的ls选项吗?我查看了ls的--help输出内容,至少没有这样的选项。 - Alex Hall
1
@AlexHall:谢谢;简而言之,尝试使用“-1”(数字一);实际上,“ls”默认为“裸”输出,即仅文件名,但在输出到终端时使用基于列的布局(每行多个文件名)。要获取每个输出行一个文件名(如果我没记错,这就是“dir / b”所做的),请使用“-1”选项,当stdout未连接到终端时(例如发送到管道或输出文件时)实际上隐含启用。 - mklement0

6

列出某个目录的内容,不包括子目录

我喜欢使用ls选项,例如:

  • -l:使用长格式列表显示
  • -t:按修改时间排序,最新的排在前面
  • -r:倒序排序
  • -F--classify:在条目后追加指示符(*、/、=、>、@、|)
  • -h--human-readable:与-l和-s一起使用时,以1K、234M、2G等形式显示文件大小

有时还会使用--color和其他选项(参见ls --help)。

列出除文件夹以外的所有内容

这将显示文件、符号链接、设备、管道、套接字等。

因此,命令为:

find /some/path -maxdepth 1 ! -type d

可以轻松按日期排序:

find /some/path -maxdepth 1 ! -type d -exec ls -hltrF {} +

仅列出 文件

或者

find /some/path -maxdepth 1 -type f

按大小排序:

find /some/path -maxdepth 1 -type f -exec ls -lSF --color {} +

防止显示隐藏条目列表:

为了不显示那些以点开头的隐藏条目,您可以添加 ! -name '.*'

find /some/path -maxdepth 1 ! -type d ! -name '.*' -exec ls -hltrF {} +

然后,您可以将/some/path替换为.以列出当前目录,或使用..来列出上级目录


2

查找文件:ls -l /home | grep "^-" | tr -s ' ' | cut -d ' ' -f 9

查找目录:ls -l /home | grep "^d" | tr -s ' ' | cut -d ' ' -f 9

查找链接:ls -l /home | grep "^l" | tr -s ' ' | cut -d ' ' -f 9

tr -s ' ' 命令将输出转换为以空格分隔的文件,cut 命令指定分隔符为一个空格,并返回第9个字段(始终是文件名/目录名/链接名)。

我经常使用这个命令!


哇!如果文件名包含空格怎么办? - F. Hauri - Give Up GitHub
使用“9-”获取第9个字段之后的所有内容。链接也会受到影响,因为它们将位于第9个字段之后。 - Richard

2

你还可以使用 ls 命令与 grepegrep 命令一起使用,并将其作为别名放入你的配置文件中:

ls -l | egrep -v '^d'
ls -l | grep -v '^d'

我不会将其放入脚本中,因为上述原因,但另一个快速且不太正式的解决方案是:ls -F | grep -v '/$'。 - mooie
@mooie,'/$' 是什么意思?为什么它会从 ls 的输出中删除目录? - Classified
1
@分类 "ls -F" 在每个目录路径后面立即显示一个斜杠("/")。 "grep" 使用美元符号("$")表示行尾。 因此,"grep '/$'" 将匹配由 "ls -F" 输出的所有以斜杠结尾的行,即目录。 "grep -v" 打印所有不匹配的行,即除了目录之外的所有内容,这将是文件名(和符号链接)。 - mooie

1

欢迎您!

ls -l | grep '^-'

只想要名称,使用管道传输到cutawk

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

ls -l | grep '^-' | cut -d " " -f 13

0
{ find . -maxdepth 1 -type f | xargs ls -1t | less; }

添加了xargs使其正常工作,并使用-1而不是-l仅显示文件名而不包含其他ls信息


这有一定的优点,它强制按时间排序,尽管使用find -printf0'...' | sort -z可能有更简洁的方式来实现这一点。 - tripleee

0

此方法不使用外部命令。

bash$ res=$( IFS=$'\n'; AA=(`compgen -d`); IFS='|'; eval compgen -f -X '@("${AA[*]}")' )

bash$ echo "$res"
. . .

0

你可以选择以下之一:

echo *.* | cut -d ' ' -f 1- --output-delimiter=$'\n'
echo *.* | tr ' ' '\n'
echo *.* | sed 's/\s\+/\n/g'
ls -Ap | sort | grep -v /   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接