我有一个文件,其中包含不同文件的位置,称为locationfile.txt
它包含:
/home/user/documents/file1
/home/user/file2
/home/user/file3
每个文本文件大约有 10 行,我想将所有文件输出到另一个名为finalfile
.
我发现如果我这样做
cat locationfile.txt | while read line; do cat "$line"; done
这会将所有文件打印在一起,使其成为大约 30 行的文本文件。
我的问题是,如何将文件输出包含在文本之间的文件位置,如下所示:
/home/user/documents/file1
text
text
text
""
/home/user/file2
text
text
text
""
/home/user/file3
text
text
text
""
答案1
在对文件名cat
执行echo
or操作之前:printf
while read line; do printf '%s\n' "$line"; cat "$line"; done <locationfile.txt >finalfile
或者,更具可读性:
while read line; do
printf '%s\n' "$line"
cat "$line"
done <locationfile.txt >finalfile
请注意,这要求所有路径中locationfile.txt
都没有路径\
。
尽管\
在路径名中包含非常不寻常,但这样做会更安全
while read -r line; do
printf '%s\n' "$line"
cat "$line"
done <locationfile.txt >finalfile
...没有相同的限制。
添加检查以确保文件确实存在,如果不存在则输出警告:
while read -r line; do
if [[ -f "$line" ]]; then
printf '%s\n' "$line"
cat "$line"
else
printf 'Warning: "%s" does not exist\n' "$line" >&2
fi
done <locationfile.txt >finalfile
这里的“不存在”意味着“至少不是一个常规文件”。
如果您""
也想要那里,作为一种文件内容结束标记,只需将其放在后面即可cat
:
while read -r line; do
if [[ -f "$line" ]]; then
printf '%s\n' "$line"
cat "$line"
echo '""'
else
printf 'Warning: "%s" does not exist\n' "$line" >&2
fi
done <locationfile.txt >finalfile
最后,给事物提供自记录的名称:
while read -r file_path; do
if [[ -f "$file_path" ]]; then
printf '%s\n' "$file_path"
cat "$file_path"
echo '""'
else
printf 'Warning: "%s" does not exist\n' "$file_path" >&2
fi
done <file_paths.txt >files_concat_with_paths.txt
答案2
while read file; do
( echo "$file"; cat "$file"; echo '"""' ) >> /path/to/outputfile
done < /path/to/filelist
答案3
如果您有 GNU awk,这里有一个选项,可以完全避免 shell 循环:
xargs -d '\n' -a locationfile.txt gawk 'BEGINFILE{print FILENAME} 1' > newfile
或使用 GNU sed:
xargs -d '\n' -a locationfile.txt sed -s '1F' > newfile
如果您不关心文件名的确切格式,那么您可以使用此技巧head
:
xargs -d '\n' -a locationfile.txt head -vn -0 > newfile
(-n -0
告诉head
输出除第一个 0 之外的所有行,即所有行)。
答案4
您可以添加echo "$line"
到循环中:
cat locationfile.txt | while read line; do echo "$line" && cat "$line"; done