在unix中合并保留原始序列的多个文件



我在目录中有多个(超过100个)文本文件,如

files_1_100.txt
files_101_200.txt

文件的内容是一些变量的名称,如files_1_100.txt包含一些介于1到100 之间的变量名称

"var.2"
"var.5"
"var.15"

类似地,files_201_300.txt包含101到200 之间的一些变量

"var.203"
"var.227"
"var.285"

CCD_ 3作为

"var.1010"
"var.1006"
"var.1025"

我可以使用命令合并它们

cat files_*00.txt > ../all_files.txt

但是,文件的内容并不遵循父文件中的内容。例如all_files.txt显示

"var.1010"
"var.1006"
"var.1025"
"var.1"
"var.5"
"var.15"
"var.203"
"var.227"
"var.285"

那么,我如何确保files_1_100.txt的内容先出现,然后是files_201_300.txt,再是files_1001_1100.txt,使得all_files.txt的内容是

"var.1"
"var.5"
"var.15"
"var.203"
"var.227"
"var.285"
"var.1010"
"var.1006"
"var.1025"

让我试试,但我认为这会奏效:

ls file*.txt | sort -n -t _ -k2 -k3 | xargs cat

这个想法是将文件列表进行排序,然后将它们传递给cat命令。

排序使用几个选项:

  • -n-使用数字排序而不是字母排序
  • -t-使用下划线字符将输入(文件名)划分为多个字段
  • -k2-k3-先按第2个字段排序,然后按第3个字段排序(2个数字)

您已经说过,您的文件名为file_1_100.txt、file_101_201.txt等。如果这意味着(似乎表明)第一个数字"chunk"总是唯一的,那么您可以省略-k3标志。只有当您最终使用file_100_2.txt和file_100_10.txt时,才需要该标志,因为您必须查看第二个数字"chunk"来确定首选顺序。

根据您正在处理的文件数量,您可能会发现指定glob(文件*.txt)可能会淹没shell,并导致行过长的错误。如果是这样的话,你可以这样做:

ls | grep '^file.*.txt$' | sort -n -t _ -k2 -k3 | xargs cat

您可以使用printf sort并将其管道传输到xargs cat:

printf "%s" f*txt | sort -z -t_ -nk2 | xargs -0 cat > ../all_files.txt

请注意,整个管道都在处理以NULL结尾的文件名,因此确保该命令甚至适用于带有空格/换行符等的文件名。

如果文件名没有任何特殊字符或空格,那么其他答案应该是简单的解决方案。否则,请尝试这种基于rename的方法:

$ ls files_*.txt
files_101_200.txt  files_1_100.txt
$ rename  's/files_([0-9]*)_([0-9]*)/files_000$1_000$2/;s/files_0*([0-9]{3})_0*([0-9]{3})/files_$1_$2/' files_*.txt
$ ls files_*.txt
files_100_100.txt  files_101_200.txt
$ cat files_*.txt > outputfile.txt
$ rename 's/files_0*([0-9]*)_0*([0-9]*)/files_$1_$2/' files_*.txt

cat file_*的默认排序行为是按字母排序,而不是按数字排序。

按数字顺序列出它们,然后对每个进行cat操作,将输出附加到某个文件中。

ls -1| sort -n |xargs -i cat {} >> file.out

您可以尝试使用for循环并逐个添加文件(当数字不是零填充时,-v会对文件进行正确排序)

for i in $(ls -v files_*.txt)
do
    cat $i >> ../all_files.txt
done

或更方便的单行:

for i in $(ls -v files_*.txt) ; do cat $i >> ../all_files.txt ; done

您也可以使用Awk通过拆分和排序ARGV:来实现这一点

awk 'BEGIN {
    for(i=1; i<=ARGC-1; i++) {
        if(i > 1) {
            j=i-1
            split(ARGV[i], curr, "_")
            split(ARGV[j], last, "_")
            if (curr[2] < last[2]) {
                tmp=ARGV[i]
                ARGV[i]=ARGV[j]
                ARGV[j]=tmp
            }
        }
    }
}1' files_*00.txt

相关内容

最新更新