如何在 Linux 中为每个输出行列出一个文件名?
Posted
技术标签:
【中文标题】如何在 Linux 中为每个输出行列出一个文件名?【英文标题】:How do I list one filename per output line in Linux? 【发布时间】:2011-04-22 15:01:52 【问题描述】:我正在使用ls -a
命令获取目录中的文件名,但输出在一行中。
像这样:
. .. .bash_history .ssh updater_error_log.txt
我需要一个内置的替代方法来获取文件名,每个文件名都在一个新行上,如下所示:
.
..
.bash_history
.ssh
updater_error_log.txt
【问题讨论】:
ls 旨在显示供人类消费的列表。如果您将 ls 用于任何其他目的(例如,获取要迭代的脚本中的文件列表),那么您肯定使用了错误的工具。 @juliano - 它实际上是由 python 脚本使用的。为什么你称它为错误的工具? @fixxer 当您将ls
传送到python 时,ls
将按照我在回答中的说明每行输出一个文件。
@fixxxer:那你确实是用错了。它格式化列表以在用户终端中输出。它可能会替换文件名中的特殊字符,它可能会省略具有特殊含义的字符,等等......换句话说,ls formats 给用户一个列表。您需要未格式化的文件名。您没有使用 python 'glob' 模块的任何特殊原因? docs.python.org/library/glob.html还有'fnmatch'、'dircache'等。
@fixxer 你真的让ls
输出到python
并观察到python中的单行输出吗?
【参考方案1】:
使用-1
选项(注意这是“一个”数字,而不是小写字母“L”),如下所示:
ls -1a
不过,首先,请确保您的 ls
支持 -1
。 GNU coreutils(安装在标准 Linux 系统上)和 Solaris 可以;但如果有疑问,请使用man ls
或ls --help
或查看文档。例如:
$ man ls
...
-1 list one file per line. Avoid '\n' with -q or -b
【讨论】:
+1 我不知道 -1(-l 是(不是一个))它显示在手册页中,但我一直在阅读它:) @slashmais - 啊,好点 - 容易出错。我在答案中澄清了。 @dty:对于 GNU,您可以在ls --help
输出中记录此内容...始终安装 ;-)
在 Google 上搜索 linux ls one file per line
,这是最热门的文章。无法相信所选择的答案是多么冗长,或者这个答案的投票数比通过管道传递给 cat 的答案要少。 ls -1
ftw.
ls
在输出未连接到终端时默认为 -1
行为。【参考方案2】:
是的,您可以轻松地让ls
每行输出一个文件名:
ls -a | cat
解释:命令ls
感知输出是到终端还是到文件或管道,并进行相应调整。
因此,如果您将ls -a
传递给 python,它应该可以在没有任何特殊措施的情况下工作。
【讨论】:
哇,这太棒了。优于公认答案的优势 - 这个实际上适用于 android / adb shell - 其中ls
只是一些精简版本,因此不支持-1
您如何避免在输出中显示.
和..
“文件”?
@matanster:这取决于,你想看点文件吗?如果没有,只需删除 -a 选项。【参考方案3】:
Ls 专为人类消费而设计,you should not parse its output。
在 shell 脚本中,在少数情况下,解析 ls 的输出确实是实现预期效果的最简单方法。由于 ls 可能会破坏文件名中的非 ASCII 字符和控制字符,因此这些情况是不需要从 ls
获取文件名的情况的子集。
在 python 中,绝对没有理由调用ls
。 Python 内置了 ls
的所有功能。使用os.listdir
列出目录的内容,使用os.stat
或os
获取文件元数据。 os
模块中的其他功能也可能与您的问题相关。
如果您通过 ssh 访问远程文件,列出文件名的一种相当可靠的方法是通过 sftp:
echo ls -1 | sftp remote-site:dir
每行打印一个文件名,与ls
实用程序不同,sftp
不会破坏不可打印的字符。您仍然无法可靠地列出文件名包含换行符的目录,但这种情况很少发生(请记住,这是一个潜在的安全问题,而不是可用性问题)。
在python中(注意shell元字符必须在remote_dir
中转义):
command_line = "echo ls -1 | sftp " + remote_site + ":" + remote_dir
remote_files = os.popen(command_line).read().split("\n")
对于更复杂的交互,在文档中查找 sftp 的批处理模式。
在某些系统(Linux、Mac OS X,可能还有其他一些 unice,但绝对不是 Windows)上,另一种方法是使用 sshfs 通过 ssh 挂载远程文件系统,然后在本地工作。
【讨论】:
我通过 SSH 连接到远程机器。我发现无法在远程机器上单行执行 os.listdir 之类的 python 函数。因此,这个问题。我不想编写一个简单列出文件的脚本。有没有其他方法可以解决这个问题? @fixxxer:ssh 确实改变了这种情况,这是您在原始问题中应该提到的那种事情!我认为 sftp 适合您的用例。 我很抱歉造成混乱。有没有办法我也可以在“命令行”中插入密码? @fixxxer:我不知道,ssh 的作者对以纯文本形式存储的密码不屑一顾,而且往往不会让这变得容易。你真的应该设置基于密钥的身份验证(网上有很多教程和superuser.com 上的问题)。【参考方案4】:你可以使用ls -1
ls -l
也会做这项工作
【讨论】:
最佳答案已经提到了您所说的确切内容。该问题还特别指出不应使用ls -l
。【参考方案5】:
你也可以使用ls -w1
这允许设置列数。 来自 ls 的联机帮助页:
-w, --width=COLS
set output width to COLS. 0 means no limit
【讨论】:
【参考方案6】:ls | tr "" "\n"
【讨论】:
【参考方案7】:很简单,只要您的文件名不包含换行符:
find . -maxdepth 1
如果您将它传递到另一个命令中,您可能更喜欢用空字节而不是换行符分隔文件名,因为空字节不能出现在文件名中(但换行符可能):
find . -maxdepth 1 -print0
在终端上打印可能会显示为一行,因为通常不会打印空字节。某些程序可能需要特定选项来处理以空值分隔的输入,例如sort
的-z
。您自己的脚本同样需要考虑这一点。
【讨论】:
以上是关于如何在 Linux 中为每个输出行列出一个文件名?的主要内容,如果未能解决你的问题,请参考以下文章