ubuntuusers.de

Bash Befehl für Teilstring aus Dateien

Status: Ungelöst | Ubuntu-Version: Ubuntu 20.10 (Groovy Gorilla)
Antworten |

passt42

Anmeldungsdatum:
16. Juli 2012

Beiträge: 85

Hallo allerseits.

Ich suche idealerweise einen zusammengesetzten Bash Befehl oder sonst ein Shell Skript, mit dem ich alle Dateien eines Verzeichniss auflisten lasse und dazu aus jeder Datei einen Teilstring anzeigen lassen. Die Ausgabe soll dann zeilenweise Datum/Uhrzeit (in long-iso), Dateiname und den Teilstring enthalten.

1
2
3
4
5
6
7
8
#Der Teilstring ist immer die ersten sechs Zeichen der zweiten Zeile:
   sed -n 2,2p dateiname |cut -c 1-6

#Verknüpft mit find sieht das dann so aus:
   find ./ -type f -maxdepth 0 -print0 |xargs -0 -n1 sed -n 2,2p |cut -c 1-6

#Die Dateiliste soll in etwa so aussehen:
   ls -l --time-style=long-iso ./ |awk '{print $6, $7, $8}'

Wie kann ich beides so wie gewünscht verbinden?

Vielen Dank, passt

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4453

Wohnort: Göttingen

Hm, also so ganz klar ist mir noch nicht, was Du möchtest. Also wie ich das verstehe, möchtest Du eine Ausgabe, wie die, die in Zeile 8 produziert wird, nur das dahinter noch die ersten sechs Zeichen der zweiten Zeile geschrieben werden? Hab ich das so richtig verstanden?

EDIT: Wenn ich das so richtig verstanden habe, dann sollte folgendes die Aufgabe erledigen:

while read line; do ls -l --time-style=long-iso "$line" | awk '{printf $6" "$7" "$8" " }'; sed -n 2,2p "$line" |cut -c 1-6;done < <(ls -p | grep -v '/$')

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17620

Wohnort: Berlin

Was cut kann, kann sed auch, und was xargs kann, kann find.

1
2
3
sed -n 2,2p dateiname |cut -c 1-6
# wird zu:
sed -rn "2s/^(.{6}).*/\1/p" dateiname

und find/xargs zu:

1
find ./ -maxdepth 1 -type f -exec sed -rn "2s/^(.{6}).*/\1/p" {} ";"

Allerdings meine ich, Du brauchst -maxdepth 1, nicht 0. Und wenn Du nicht rekursiv suchen willst, wieso dann überhaupt find?

Haben die Dateien vielleicht alle die gleiche Endung, wie 'csv'?

1
2
3
4
for f in *.csv
do
    sed -rn "2s/^(.{6}).*/\1/p" $f
done 

Mit dem Datumscode:

1
2
3
4
5
6
for f in *.csv
do
    zeichen1bis6=$(sed -rn "2s/^(.{6}).*/\1/p" $f)
    zeit=$(ls -l --time-style=long-iso ./ |awk '{print $6, $7, $8}')
    echo $zeit $zeichen1bis6
done 

Allerdings kann find auch die formatierte Ausgabe übernehmen:

1
find ./ -maxdepth 1 -type f -printf "%TY-%Tm-%Td %TH:%TM %f" -exec sed -rn "2s/^(.{6}).*/\1/p" {} ";"

Falls Du eine Dateiendung hast, fügst Du etwas wie -name "*.csv" nach "-type f" ein.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13204

Zeig doch mal eine Beispielausgabe, wie Du sie Dir vorstellst.

Anmerkung: find kann auch Daten formatiert ausgeben und ansonsten gibt es auch noch stat für formatierte Ausgabe der Meta-Daten eines Dateisystemobjektes.

passt42

(Themenstarter)

Anmeldungsdatum:
16. Juli 2012

Beiträge: 85

@Doc_Symbiosis Dein Ergebnis ist das, was ich mir vorstelle. Um nach Zeit zu sortieren, habe ich am Ende das ls um den Parameter -t ergänzt. Dabei stelle ich jetzt aber fest, dass long-iso als Zeitformat doch nicht so ideal ist, da dort keine Sekunden oder gar Millisekunden angezeigt werden.

@user_unknown Das hast du für mich schön und einfach erklärt 👍 Da der Zeichensatz OEM840 ist, kommt es zu Problemen mit Umlauten. Nach der Ausgabe der ersten sechs Zeichen der zweiten Zeile, wird, beim Vorkommen eines Umlautes, ab dann der Rest der Zeile ebenfalls ausgegeben.

Als finales Ergebnis möchte ich alle Dateien anzeigen, die zeitlich direkte aufeinander folgen, dabei max 3 Sekunden auseinander liegen und bei denen die selben 6 Zeichen ausgegeben werden.

Ich hatte eigentlich vor dieses Ergebnis nach Excel zu werfen und dort die Auswertung zu machen. Aber über die Bash geht das wahrscheinlich genauso gut und ist dann auch noch eine Übung für mich.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13204

passt42 schrieb:

Als finales Ergebnis möchte ich alle Dateien anzeigen, die zeitlich direkte aufeinander folgen, dabei max 3 Sekunden auseinander liegen und bei denen die selben 6 Zeichen ausgegeben werden.

Hab ich das richtig verstanden? Du willst alle Dateien mit dem selben Schlüssel (erste sechs Zeichen der zweiten Zeile) zusammenfassen und dann pro Schlüssel alle die Dateien auflisten, die maximal drei Sekunden auseinander liegen? So etwas würde ich dann lieber in Ruby schreiben - das ist doch schon etwas kompliziert, z.B. so Spoiler Alert (ohne formatierte Ausgabe):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/ruby

# Pass nothing -> read current dir
# Pass one arg which is a directory -> read that dir
# else use all file name arguments

dir = if ARGV.empty?
  '.'
elsif ARGV.size == 1 && File.directory?(ARGV.first)
  ARGV.first
end

files = dir ? Dir.children(dir).map {|ch| dir + "/" + ch} : ARGV

FileMeta = Struct.new :name, :key, :mtime

def key(file_name)
  File.open(file_name, 'rb') {|io| io.readline; io.readline[0, 6]}
end

all = Hash.new {|h, k| h[k] = []}

files.each do |file|
  f = FileMeta.new file, key(file), File.stat(file).mtime
  all[f.key] << f
end

all.each do |key, list|
  puts key

  list.sort_by! {|data| data.mtime}

  last = FileMeta.new "", key, Time.new(0)
  last_printed = false

  list.each do |data|
    tmp = data.mtime - last.mtime <= 3

    if tmp
      p last unless last_printed
      p data
    end

    last = data
    last_printed = tmp
  end

  puts
end

passt42

(Themenstarter)

Anmeldungsdatum:
16. Juli 2012

Beiträge: 85

passt42 schrieb: Als finales Ergebnis möchte ich alle Dateien anzeigen, die zeitlich direkte aufeinander folgen, dabei max 3 Sekunden auseinander liegen und bei denen die selben 6 Zeichen ausgegeben werden.

Hab ich das richtig verstanden?

Ich habe es falsch formuliert. Die Dateien sollen nach Erstellungszeit sortiert werden. Es interessieren nur die Nachbarn, die einen gleichen Teilstring haben. Davon sollen die Dateien markiert werden, die als Nachbarn 3sek auseinander liegen.

Falls der Hintergrund interessiert: Es handelt sich hierbei um CSV-Dateien, die nach User-Eingabe von unserem ERP-System exportiert werden. Diese CSV-Dateien werden dann von unserer Etikettierlösung automatisiert verarbeitet und ausgedruckt. Der User hat festgestellt, dass es sporadisch zu Verzögerungen von zahlreichen Sekunden im Ausdruck der einzelnen Dateien kommt, obwohl die Dateien zeitgleich exportiert worden sein sollen. Jetzt möchte ich feststellen, ob diese Verzögerungen sich in der Erstellzeit der CSV-Dateien wiederspiegelen. Der nächste Schritt wäre zu schauen ob das nachgelagerte Etikettiersystem diese Verzögerung auslöst.

Antworten |