如何在Bash中从文件列表中连接多个文件?

16

我有一个文本文件,其中包含了一系列文件名。我想把它们的内容合并起来。什么是最好的方法呢?我正在尝试这样做,但它似乎过于复杂:

let count=0
while read -r LINE
do
    [[ "$line" =~ ^#.*$ ]] && continue
    if [ $count -ne 0 ] ; then
        file="$LINE"
        while read PLINE
        do
            echo $PLINE | cat - myfilejs > /tmp/out && mv /tmp/out myfile.js
        done < $file
    fi
    let count++
done < tmp

我跳过了注释行,但遇到了问题。必须有更好的方法来解决这个问题,而不需要使用两个循环。谢谢!

6个回答

20

或者使用一个简单的命令

cat $(grep -v '^#' files) > output

2
@CharlesDuffy 我怀疑在这种特定的应用程序中,人们真的会使用空格分隔的文件名。相反,我建议改进,因为在我看来,一行代码比8行脚本更好。你真的曾经使用过带有空格的文件名吗? - Bernhard
5
@Bernhard 不要误解我的意思,但我们经常处理带有空格的文件名。我们支持那些不知道区别的用户,如果编写一个可以处理它们的脚本很容易,为什么不这样做呢? - kojiro
3
如果没有注释的话,cat $(cat files) > output 的意思是将 files 中列出的所有文件合并成一个,并将结果输出到 output 文件中。 - mustafa.0x

8

xargs cat < files

xargs相比于$(cat)的优点在于,cat会扩展成一个巨大的参数列表,如果列表中有很多文件,则由于Linux命令行长度的限制可能会失败。

不考虑#的示例:

printf 'a\nb\nc\n' > files
printf '12\n3\n' > a
printf '4\n56\n' > b
printf  '8\n9\n' > c
xargs cat < files

输出:

12
3
4
56
8
9

根据OP的要求,以下是忽略#的更具体示例:

printf 'a\nb\n#c\n' > files
printf '12\n3\n' > a
printf '4\n56\n' > b
printf  '8\n9\n' > c
grep -v '^#' files | xargs cat

输出:

12
3
4
56

相关链接:如何使用管道将find命令返回的文件列表传递给cat以查看所有文件


5
#!/bin/bash

files=()
while read; do
    case "$REPLY" in
        \#*|'') continue;;
        *) files+=( "$REPLY" );;
    esac
done < input
cat "${files[@]}"

这种方法的优点如下:

  1. 唯一使用的外部命令cat,只会执行一次。
  2. 它非常注意维护每行/文件名中的重要空格。

与此答案相比: cat $(grep -v '^#' files)>输出有明显的优势吗? - user1470511
3
是的,如果任何文件名中含有空格,grep命令的答案可能会出错。 - kojiro

3
{
  while read file
  do
    #process comments here with continue
    cat "$file"
  done
} < tmp > newfile

我修复了变量 file 的使用。是否真的需要大括号? - chepner
@chepner:不需要,因为变量的使用是明确无误的。 - Ignacio Vazquez-Abrams

1

你觉得这个命令怎么样:cat $(cat listoffiles) | grep -v "^#"


1
你是不是指的是 cat $(grep -v '^#' listoffiles)?那么空格问题怎么办? - kojiro
好的,只要文件名中没有空格。 - chepner
1
@chepner 只要在 listoffiles 中转义空格或将名称加引号即可。 - loxaxs

0
我最终得到了这个:
sed '/^$/d;/^#/d;s/^/cat "/;s/$/";/' files | sh > output

步骤:
  1. sed文件 中删除空行和注释行。

  2. sed 然后将每一行包装在 cat ""; 中。

  3. 脚本然后通过管道传输到 sh 中,并且输出到 output


我忘了提到,这种方式通过将文件名用引号括起来来粗略地处理空格。 - sh3rmy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接