2017-01-13 2 views
0

Ich möchte Dateien verketten, die einen bestimmten Namen Muster folgen, das heißt ich habe viele Dateien wie:Concatenate Dateien mit einem bestimmten Namensmuster (Unix)

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 
. 
. 
. 

... und ich will immer die Dateien verketten , die den gleichen "Namen" haben? und die gleiche letzte Zahl (1 oder 2), dh aus dem Beispieldatei über verketten

"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" 
. 
. 
. 

ich zum ersten Mal ein Skript wie zu schreiben versucht:

for f1 in *_?_1.txt 
do 
f2="${f1%%_?_1.txt}_?_2.txt" 
. 
. 
. 

... aber ich relized (ein vollständiger Unix Rookie zu sein), dass dies nicht der Weg ist, den Namen der anderen übereinstimmenden Dateien zu erhalten, so dass die Dateien ausgewählter Namen in loop verknüpft werden können ... Ich wäre dankbar für alle Hinweise (vorzugsweise mit Unix-Befehlen) aber ich bin tatsächlich für jede andere Lösung geöffnet). Vielen Dank!

+0

Wie sollte der Name der verketteten Dateien lauten? – Inian

Antwort

0

Hier ist der Schnitt!

Zuerst, sorry für einen Fehler vor. Ich weiß nicht, was in letzter Zeit in mich gekommen ist.

Zweitens fragt Frage nicht, wie Sie Dateien verketten möchten.

Wenn indem sie sie mit Unix-Tagging Sie es in Shell (Bash zum Beispiel) tun wollte, na ja, das wird man bekommt, was man wollte:

#! /bin/bash 

for file in $(ls ./name*1.txt) 
do 
    echo $file 
done 

Dadurch werden alle Dateien ausdrucken (eine pro jeder Zeile) filtern sie nach Wildcard (mit '*' im Namen). Sie müssen lesen Befehl oder cat mit vielen Rohrleitungen zu verketten Inhalt von Dateien, deren Namen in $ Datei Variable sein.

Wenn Sie viele Dateien haben, wird dies ein wenig unpraktisch sein. Es wird immer noch funktionieren, aber es ist unhöflich gegenüber Ihrem System.

Daher empfehle ich Ihnen, einige echte Skriptsprache zu verwenden, um zu erreichen, was Sie in einem Prozess erreichen möchten. Hier ist ein vollständiges Beispiel in 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() 

Wenn Sie sicherstellen möchten, dass Ihre Dateien sortiert werden, bevor Verkettung(), um für Schleife sortiert add:

nur eine Gruppe von
for x in sorted(glob.iglob(...)): ... 

wird dies obwohl verketten Dateien, die durch die Variable namespattern angegeben werden. Sie müssen dieses Skript also einige Male ausführen. Eine der Ideen, wie man sie gruppiert, wird hier von hansaplast präsentiert.

+0

sollten Sie sagen, dass dies Python ist – hansaplast

+0

Was hat das überhaupt mit der Frage zu tun? Es ist ein zufälliges Code-Snippet ohne Erklärung; es ist in einer anderen (nicht näher bezeichneten) Programmiersprache; Es löst das Problem nicht. – melpomene

+0

Sorry Leute! Irgendwie sah Python in Tags. Sehr gut, ich werde bearbeiten! – Dalen

0

Wie Sie hier auf alle Programmiersprachen offen sind, ist ein Python-Lösung:

import os 
from collections import defaultdict 

buckets = defaultdict(list) 

for filename in os.listdir('files/'): 
    parts = filename.split('.')[0]('_') 
    # group by string before first _ and number after last _ 
    # "nameX_4_1.txt" becomes ("nameX", "1") 
    key = (parts[0], parts[-1]) 
    buckets[key].append(filename) 

# files are now grouped, output them (order is not predictable) 
for key,value in buckets.items(): 
    print(", ".join(value)) 

Beispielsitzung:

$ 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 

Das Python-Programm erwartet, dass die Dateien in files/ sein, so würden Sie brauchen um das in das tatsächliche Verzeichnis zu ändern.

Bitte kommentieren Sie, wenn Sie mehr darüber wissen möchten, was das Python-Programm macht oder ob Sie irgendwelche Funktionen vermissen.

0

Als Startpunkt können Sie diese (bash) versuchen:

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 

Notiere die erste echo Linie: es vor jeder Gruppe von Datei gedruckt wird. Statt echo können Sie auswählen (vorbereiten), in eine temporäre Datei zu schreiben, oder einen Befehl erstellen, der später ausgeführt wird. Für eine temporäre Datei würden Sie statt echo file $filecat $file >> my_temporary_file oder etwas ähnliches tun.

0

Das Problem sieht ein bisschen haarig, so würde ich wahrscheinlich Perl verwenden, nicht Shell (Warnung, nicht getesteten Code):

#!/usr/bin/env perl 
use strict; 
use warnings; 

my %groups; 

for my $file (glob '*_*_[12].txt') { 
    my $key = $file; 
    $key =~ s/_[^_]*(?=_\d\.txt\z)/_X/ or die "No match for $key"; 
    push @{$groups{$key}}, $file; 
} 

for my $group (values %groups) { 
    print "@$group\n"; 
} 

Die Idee ist, über alle Dateien in einer Schleife *_*_[12].txt Anpassung und einen normalisierten Schlüssel berechnen für jeden Namen; z.B. foobar_123_1.txt würde foobar_X_1.txt werden (wir ersetzen den Teil zwischen den letzten zwei Unterstrichen durch X).

Auf diese Weise werden alle Dateien, die Sie verketten möchten, unter demselben Schlüssel gruppiert. Am Ende schleifen wir einfach alle Gruppen und geben die Dateinamen (getrennt durch ein Leerzeichen) in jeder Gruppe aus, gefolgt von einem Zeilenumbruch.

Verwandte Themen