我想将目录中每个文件的所有文件名打印到.txt
文件。
我们假设我有一个包含3个文件的目录:
file1.txt
file2.txt
file3.txt
我尝试使用ls > output.txt
。
问题是当我打开output.txt
时,我找到了这个列表:
file1.txt
file2.txt
file3.txt
output.txt
有没有办法避免打印我重定向输出的文件名?或者更好的是有一个命令能够打印除一个文件以外的目录中文件的所有文件名吗?
答案 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.txt
是ls > 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)
使用ls
和awk
命令可以获得正确的输出。
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
返回。