我在一个名为的文件中有一个文件名列表list_of_files.txt
。
我想将该列表中每个文件的内容复制到另一个名为的文件中all_compounds.sdf
。
我应该如何从命令行执行此操作?
答案1
不要使用简单的命令替换来获取文件名(因为空格和其他特殊字符很容易中断)。请使用类似以下命令xargs
:
xargs -d '\n' -a list_of_files.txt cat > all_compounds.sdf
或者while read
循环:
while IFS= read -r file; do cat "$file"; done < list_of_files.txt > all_compounds.sdf
要安全地使用命令替换,至少将其设置IFS
为换行符并禁用通配符(通配符扩展):
(set -f; IFS=$'\n'; cat $(cat list_of_files.txt) > all_compounds.sdf)
周围的括号()
是为了在子 shell 中运行它,这样当前 shell 就不会受到这些更改的影响。
答案2
快速而肮脏的方法......
cat $(cat list_of_files.txt) >> all_compounds.sdf
请注意:这仅当列表中的文件名表现良好时才有效 - 如果它们有空格,换行符或任何对 shell 有特殊含义的字符,则会出现问题 - 使用这个答案以获得可靠的结果)
笔记
cat
反对派猫列出文件。它还会打印其内容。使用命令替换,您可以将( )
command2 $(command1)
的输出传递给( ),以连接文件。command1
cat list...
command2
cat
然后使用重定向
>>
将输出发送到文件,而不是打印到 stdout。如果要查看输出,请使用tee
:cat $(cat list_of_files.txt) | tee -a all_compounds.sdf
(如果您的文件已经存在,我已经使用了>>
代替>
和tee
开关- 这-a
附加如果文件已经存在,则写入文件而不是覆盖它)
答案3
虽然 GNUawk
是一个文本处理实用程序,但它允许通过调用运行外部 shell 命令system()
。我们可以利用这一点,如下所示:
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
这里的想法很简单:我们逐行读取文件,并从每一行创建格式化的字符串cat "File name.txt"
,然后将其传递给system()
。
实际运行如下:
$ ls
file1.txt file2.txt file3 with space.txt file_list.txt
$ awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt
Hi, I'm file2
Hi, I'm file1
Hi, I'm file3
所以我们已经完成了大部分任务 - 我们打印了列表中的所有文件。剩下的很简单:将最终输出重定向到带有>
运算符的文件中,并将其放入摘要文件中。
awk '{cmd=sprintf("cat \"%s\"",$0); system(cmd)}' file_list.txt > output.txt