在bash中连接文本文件

在bash中连接文本文件,bash,Bash,我有很多文本文件,在一个文件夹中只有一个行浮点值,我想在bash中按顺序连接它们,例如:file_1.txt,file_2.txt…file_N.txt。我想把它们放在一个txt文件中,顺序从1到N。有人能帮我吗?这是我的代码,但它只是以随机方式连接它们。多谢各位 for file in *.txt do cat ${file} >> output.txt done 这不仅适用于我,而且适用于: for file in *.txt do cat $file &g

我有很多文本文件,在一个文件夹中只有一个行浮点值,我想在bash中按顺序连接它们,例如:file_1.txt,file_2.txt…file_N.txt。我想把它们放在一个txt文件中,顺序从1到N。有人能帮我吗?这是我的代码,但它只是以随机方式连接它们。多谢各位

for file in *.txt
do 
  cat ${file} >>  output.txt  
done 
这不仅适用于我,而且适用于:

for file in *.txt
do 
  cat $file >>  output.txt  
done
您不需要
{}

但更简单的是:

cat file*.txt > output.txt
因此,如果您有评论中建议的9个以上的文件,您可以执行以下操作之一:

files=$(ls file*txt | sort -t"_" -k2g)
files=$(find . -name "file*txt" | sort -t "_" -k2g)
files=$(printf "%s\n" file_*.txt | sort -k1.6n) # Thanks to glenn jackman
然后:

cat $files

最好的方法仍然是对文件进行正确编号,因此,如果文件少于100个,请使用file_01.txt;如果文件少于1000个,则使用et file_001.txt,以此类推。


例如:

ls file*txt
file_1.txt  file_2.txt  file_3.txt  file_4.txt  file_5.txt  file_10.txt
它们只包含相应的编号

$ cat $files
1
2
3
4
5
10

您可以使用ls列出文件:

for file in `ls *.txt`
do·
  cat ${file} >>  output
done
这里讨论了一些排序技术:

使用这个:

find . -type f -name "file*.txt" | sort -V | xargs cat -- >final_file

如果文件被编号,那么排序就不会以我们人类期望的自然方式进行。为此,您必须将-V选项与
sort
命令一起使用。

正如我建议不要解析
ls
的输出一样,我们开始吧

ls
有一个“版本排序”选项,可以根据需要对编号文件进行排序。请参见下面的演示

要连接,您需要:

ls -v file*.txt | xargs cat > output

正如其他人所指出的,如果您有文件
文件1
文件2
文件3
file_123283
,这些文件的内部BASH排序将把
file_11
放在
file_2
之前,因为它们是按文本而不是数字排序的

您可以使用
sort
获得所需的订单。假设您的文件是
file#

cat $(ls -1 file_* | sort -t_ -k2,2n)
  • ls-1
    每行列出一个文件
  • sort-t
    表示用下划线将排序字段分解。这使得第二个排序字段成为文件名的数字部分
  • -k2,2n
    表示按第二个字段进行数字排序
然后,将所有文件连接在一起

一个问题是,如果您有大量文件,那么最终可能会填充命令行缓冲区。在
cat
获取文件名之前,必须首先展开
$(…)

  • 是GNU/Linux系统的简单解决方案
  • 是一种便携式替代品
这两种解决方案都适用于当前的特定情况,但通常不适用于,因为它们将与带有嵌入空格的文件名或其他元字符((未加引号的字符对shell具有特殊意义)分离

以下是使用带有嵌入空格的文件名等的解决方案:


首选解决方案,适用于支持
sort-z
xargs-0
系统(例如Linux、OSX、*BSD):

printf“%s\0”文件*.txt | sort-z-t |-k2,2n | xargs-0 cat>out.txt
使用NUL(空字符,
0x0
)分隔文件名,从而安全地保留其边界

这是最健壮的解决方案,因为它甚至可以正确处理带有嵌入换行符的文件名(尽管这种文件名在实践中非常罕见)。不幸的是,
sort-z
xargs-0
与POSIX不兼容


POSIX兼容解决方案,使用
xargs-I

printf“%s\n”文件*.txt | sort-t |-k2,2n | xargs-I%cat%>out.txt
处理是基于行的,由于使用了
-I
cat
,每个输入文件名调用一次,使得此方法比上面的方法慢。

这对我来说很有效

for i in $(seq 0 $N); do [[ -f file_$i.txt ]] && cat file_$i.txt; done > newfile
或者,更简洁地说

for i in $(seq 0 $N); do cat file_$i.txt 2> /dev/null ;done > newfile

假设文件按您希望的顺序按字母顺序排序,则应该可以工作。可能的重复项仅对{1..9}中的N有效。一旦N超过9,文件将无法正确排序。另一种使用排序的方法:如果知道数字从文件名的第6个字符开始:
printf“%s\N”file.*.txt | sort-k1.6n
printf“%s\N”file.*.txt
是更可取的形式:
ls file.*.txt
也这样做,但不必要地调用外部可执行文件<代码>查找-名称“file_*txt”,除了调用外部可执行文件之外,还可能做一些不同的事情,因为它处理整个子树(即,子目录中的文件也可以被拾取;添加
-maxdepth 1
),以避免这种情况。它在这种情况下起作用,但请注意,如果要将排序限制为单个字段,必须指定该字段索引两次,例如:
-k2,2g
-否则,该字段和该行的其余部分将用作排序键。此外,除非您的数字不是十进制的,或具有
+
前缀或采用指数表示法,否则请使用
n
not
g
进行数字排序(避免舍入错误,更快-请参阅)。因此,排序键应为:
-k2,2n
-k1.6,1n
。在这种情况下这不是一个问题,但总的来说值得注意:这个解决方案将打破带有嵌入空格的文件名。它对我也适用,但我不能按名称的顺序排列它们。我的输出txt文件从文件10开始到19,然后是1,20,2-9,但我想让它们按数字顺序从1到20。谢谢,您必须将文件从name_1.txt重命名为name_01.txt。创建类似以下内容的文件:触摸文件{01..20}。txt除了不解决排序问题外:直接使用globbing(路径名扩展)更简单、更健壮,而且速度更快:
对于*.txt中的文件
-解析
ls
输出不是一个好主意;看见正如所写的(无需排序),您的命令可以简化
cat $(ls -1 file_* | sort -t_ -k2,2n)
for i in $(seq 0 $N); do [[ -f file_$i.txt ]] && cat file_$i.txt; done > newfile
for i in $(seq 0 $N); do cat file_$i.txt 2> /dev/null ;done > newfile