在bash中连接文本文件
我有很多文本文件,在一个文件夹中只有一个行浮点值,我想在bash中按顺序连接它们,例如:file_1.txt,file_2.txt…file_N.txt。我想把它们放在一个txt文件中,顺序从1到N。有人能帮我吗?这是我的代码,但它只是以随机方式连接它们。多谢各位在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
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系统的简单解决方案
- 是一种便携式替代品
首选解决方案,适用于支持
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
notg
进行数字排序(避免舍入错误,更快-请参阅)。因此,排序键应为:-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