Loops 使用特定命名模式连接文件(unix)

Loops 使用特定命名模式连接文件(unix),loops,unix,concatenation,sh,string-matching,Loops,Unix,Concatenation,Sh,String Matching,我想连接遵循特定名称模式的文件,即我有许多文件,如: nameX_4_1.txt nameX_983_2.txt nameX_5_1.txt nameX_2_2.txt nameY_7_1.txt nameY_4_2.txt nameY_8_1.txt nameY_3_2.txt nameY_9_1.txt nameY_6_2.txt . . . …我希望始终连接具有相同“名称”和相同最后编号(1或2)的文件,即从上面的示例文件连接 "nameX_4_1.txt" and "nameX_5_1

我想连接遵循特定名称模式的文件,即我有许多文件,如:

nameX_4_1.txt
nameX_983_2.txt
nameX_5_1.txt
nameX_2_2.txt
nameY_7_1.txt
nameY_4_2.txt
nameY_8_1.txt
nameY_3_2.txt
nameY_9_1.txt
nameY_6_2.txt
.
.
.
…我希望始终连接具有相同“名称”和相同最后编号(1或2)的文件,即从上面的示例文件连接

"nameX_4_1.txt" and "nameX_5_1.txt"  
"nameX_983_2.txt" and "nameX_2_2.txt"
"nameY_7_1.txt" and "nameY_8_1.txt" and "nameY_9_1.txt"
"nameY_4_2.txt" and "nameY_3_2.txt" and "nameY_6_2.txt"
.
.
.
我首先尝试编写一个脚本,如:

for f1 in *_?_1.txt
do
f2="${f1%%_?_1.txt}_?_2.txt"
.
.
.
…但我重申(作为一名完全的unix新手),这不是获取其他匹配文件名称的方法,因此可以在循环中连接选定名称的文件。。。 如果有任何提示,我将不胜感激(首选使用unix命令,但实际上我对任何其他解决方案都持开放态度)。谢谢

这里是编辑

首先,为之前的错误道歉。我不知道最近我怎么了

第二,问题并没有指定如何连接文件

如果使用Unix标记它,您希望在shell(例如Bash)中完成它,那么,这将满足您的需要:

#! /bin/bash

for file in $(ls ./name*1.txt)
do
    echo $file
done
这将打印出所有文件(每行一个),并通过通配符(名称中使用“*”)对其进行过滤。 您将不得不使用read命令或cat以及大量管道来连接文件的内容,这些文件的名称将在$file变量中

如果你有很多文件,这将是有点不切实际。它仍然可以工作,但对您的系统来说是不礼貌的

因此,我建议您使用一些真正的脚本语言在一个过程中实现所需的功能。 下面是一个完整的Python示例:

#! /usr/bin/env python
import glob

namepattern = "./name*1.txt"
outputfile = "./output.txt"
whole_text = ""
for x in glob.iglob(namepattern):
    f = open(x, "r")
    whole_text += "\n"+f.read()
    f.close()
f = open(outputfile, "w")
f.write(whole_text)
f.close()
如果要确保在连接之前对文件进行排序,请将sorted()添加到for循环:

for x in sorted(glob.iglob(...)): ...

不过,这将只连接一组文件,由namepattern变量指定。因此,您必须运行此脚本几次。hansaplast在这里介绍了如何对它们进行分组的一个想法。

由于您对任何编程语言都持开放态度,这里有一个python解决方案:

导入操作系统
从集合导入defaultdict
bucket=defaultdict(列表)
对于os.listdir('files/')中的文件名:
parts=filename.split('.')[0]('.')
#按第一个之前的字符串和最后一个之后的数字分组_
#“nameX_4_1.txt”变为(“nameX”,“1”)
键=(部分[0],部分[-1])
bucket[key].append(文件名)
#文件现在已分组,请将其输出(顺序不可预测)
对于键,以bucket.items()为单位的值:
打印(“,”。连接(值))
示例会话:

$ ls files/
nameX_2_2.txt   nameX_5_1.txt   nameY_3_2.txt   nameY_6_2.txt   nameY_8_1.txt
nameX_4_1.txt   nameX_983_2.txt nameY_4_2.txt   nameY_7_1.txt   nameY_9_1.txt

$ python script.py
nameX_2_2.txt, nameX_983_2.txt
nameY_3_2.txt, nameY_4_2.txt, nameY_6_2.txt
nameY_7_1.txt, nameY_8_1.txt, nameY_9_1.txt
nameX_4_1.txt, nameX_5_1.txt
python程序希望文件位于
files/
中,因此需要将其更改为实际目录


如果您想更多地了解python程序的功能,或者错过了任何功能,请发表评论。

作为起点,您可以尝试以下方法(bash):


注意第一行
echo
是在每组文件之前打印的。您可以选择(准备)写入一个临时文件,或者构建一个稍后执行的命令,而不是执行此
echo
。对于临时文件,您可以使用
cat$file>>my_temporary_file
或类似的方法来代替
echo file$file

问题看起来有点棘手,因此我可能会使用perl,而不是shell(警告,未测试的代码):

#/usr/bin/env perl
严格使用;
使用警告;
我的%组;
对于我的$file(glob'*.*.[12].txt'){
我的$key=$file;
$key=~s/[^]*(?=\d\.txt\z)/\ux/或死“与$key不匹配”;
推送@{$groups{$key}},$file;
}
对于我的$group(值%groups){
打印“@$group\n”;
}
其思想是循环所有匹配
*.*.[12].txt的文件,并为每个名称计算一个规范化键;e、 g.
foobar_123_1.txt
将成为
foobar_X_1.txt
(我们将最后两个下划线之间的部分替换为
X


这样,所有要连接的文件都将分组在同一个键下。最后,我们只需在所有组上循环并输出每个组中的文件名(用空格分隔),然后换行。

您应该声明这是python这与问题有什么关系?这是一个没有解释的随机代码片段;它使用不同的(未指定的)编程语言;这不能解决问题,对不起,伙计们!不知怎的,在标记中看到了Python。很好,我来编辑!连接文件的名称应该是什么?
for xy in X Y; do 
  for s12 in 1 2; do 
    echo "   $xy --- $s12"
    for file in $(ls name${xy}_*_$s12.txt); do
      echo "file $file"
    done
  done
done