从终端

时间:2017-04-30 17:04:24

标签: bash ls

我想将目录中每个文件的所有文件名打印到.txt文件。

我们假设我有一个包含3个文件的目录:

file1.txt
file2.txt
file3.txt

我尝试使用ls > output.txt

问题是当我打开output.txt时,我找到了这个列表:

file1.txt
file2.txt
file3.txt
output.txt

有没有办法避免打印我重定向输出的文件名?或者更好的是有一个命令能够打印除一个文件以外的目录中文件的所有文件名吗?

6 个答案:

答案 0 :(得分:10)

printf '%s\n' * > output.txt

请注意,这假设没有预先存在的output.txt文件 -  如果是这样,请先将其删除。

  • printf '%s\n' *使用globbing (filename expansion)以强制方式逐行打印位于当前目录中的所有文件和子目录的名称。

  • output.txt通过输出重定向> output.txt(在命令执行之前仍然发生)创建之前发生,这解释了你的问题),因此它的名字包含在输出中。

  • Globbing还避免使用ls,其在脚本编写中使用generally discouraged

答案 1 :(得分:1)

一般来说,解析ls的输出并不好,特别是在编写需要长期保持良好信誉的生产质量脚本时。请参阅此页面以了解原因:Don't parse ls output

在您的示例中,output.txtls > output.txt中输出的一部分,因为shell在运行ls之前安排重定向(到output.txt)。

为您的案例获得正确行为的最简单方法是:

ls file*txt > output.txt # as long as you are looking for files named that way

或者,将输出存储在隐藏文件中(或存储在其他目录中的普通文件中),然后将其移动到最终位置:

ls > .output.txt && mv .output.txt output.txt

更通用的解决方案是使用grep -v

ls | grep -vFx output.txt > output.txt

或者,您可以使用数组:

files=( "$(ls)" )
printf '%s\n' "${files[@]}" > output.txt

答案 2 :(得分:0)

最安全的方法是在不假设文件名的情况下使用bash数组(在内存中)或临时文件。临时文件不需要内存,因此可能更安全。类似的东西:

#!/bin/bash
tmp=$(tempfile)
ls > $tmp
mv $tmp output.txt

答案 3 :(得分:0)

RewriteRule有一个忽略选项,我们也可以使用ls命令。

  • find与忽略选项

    一起使用
    ls
  

ls -I "output.txt" > output.txt ls --ignore "output.txt" > output.txt 是一样的。此选项表示,如在手册页中,不会列出与shell PATTERN匹配的隐含条目。

  • 使用-I, --ignore

    find
  find \! -name "output.txt" > output.txt 中的

-name选项查找名称与模式匹配的文件/目录。   find排除其名称与模式匹配。

! -name
  

%P剥离路径并仅提供名称。

答案 4 :(得分:0)

使用lsawk命令可以获得正确的输出。

ls -ltr | awk '/txt/ {print $9}' > output.txt

这将只打印文件名。

答案 5 :(得分:0)

我的方式是:

ls *.txt > output.txt

请注意,shell 在运行之前总是会展开所有的 glob。在您的特定情况下,glob 扩展过程如下:

# "ls *.txt > output.txt" will be expanded as
ls file1.txt file2.txt file3.txt > output.txt

您在最终输出文件中得到“output.txt”的原因是重定向实际上在所有连接的程序之间起作用 同时强>

这意味着重定向过程不会在程序 ls 结束时发生,而是在每次 ls 产生一行输出时发生。在您的情况下,当 ls 完成生成第一行时,将创建文件“output.txt”,无论如何最终都会由 ls 返回。