从终端将目录中的文件列表打印到文本文件(但不是文本文件本身)

Print list of files in a directory to a text file (but not the text file itself) from terminal

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

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

file1.txt
file2.txt
file3.txt

我尝试使用 ls > output.txt

问题是,当我打开 output.txt 时,我发现这个列表:

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

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

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

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

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

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

最安全的方法是使用 bash 数组(在内存中)或临时文件,而不对文件名做任何假设。临时文件不需要内存,所以它可能更安全。类似于:

#!/bin/bash
tmp=$(tempfile)
ls > $tmp
mv $tmp output.txt
printf '%s\n' * > output.txt

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

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

  • 通配发生在之前 output.txt是通过输出重定向创建的> output.txt(在命令[=26=之前仍然发生) ]executed,这解释了你的问题),所以它的名字是 not included in the output.

  • Globbing 也避免使用 ls,它在脚本中的用法是 generally discouraged

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

  • 使用带忽略选项的ls

    ls -I "output.txt" > output.txt
    ls --ignore "output.txt" > output.txt
    

-I, --ignore are same. This option says, as in the man page, do not list implied entries matching shell PATTERN.

  • 使用find

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

-name option in find finds files/directories whose name match the pattern. ! -name excludes whose name match the pattern.

    find \! -name "output.txt" -printf '%P\n' > output.txt

%P strips the path and gives only names.

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

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

这将只打印文件名。

我的方式是这样的:

ls *.txt > output.txt

请注意 shell 将始终展开 运行 之前的所有 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”,无论如何最终 return 将由 ls 生成。