• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

awk 1. Zeile ignorieren [gelöst]

Hallo an alle,
ich habe die folgende Aufgabe die zwingend! mit awk zu lösen ist. Es soll ein Skript geschrieben werden, das aus der Ausgabe von"ls -l" die Rechte und den Dateinamen ausfiltert (Dateinamen dürfen auch Leerzeichen enthalten). Am Ende soll noch die Gesammtgröße aller Dateien angezeigt werden. So sieht es bis jetzt aus:
Code:
#! /bin/bash

ls -l | awk '
{ printf ("%s ", $1)
        for ( name=9; name<=NF; name++ )
        {
                printf ("%s ", $name)
                printf("\n")
                total= total + $5
        }

}

END { print "Gesamt = " total } '
Das Problem ist, das in der ersten Zeile immer das Wort "total" auftaucht, da ja bei einem ls -l immer als erste Zeile die Anzahl dr Einträge angezeigt wird.
Wie bekomme ich es hin, das die erste Zeile nicht ausgewertet und Angezeigt wird?
 
Bin jetzt kein awk-Guru, aber laut Dokumentation steht in der Varialben FNR immer die aktuelle Zeilennummer drin. Die könntest du auf größer 1 abfragen...
 
So sieht das bei mir online eingegeben aus:
Code:
echo "1
> 2
> 3" | awk '
>      { if ( NR == 1 ) next
>        print
>      }'
2
3

Haveaniceday
 
Mir kam noch eine Idee: An den Anfang des awk-Script einfach folgendes setzen:
Code:
BEGIN { getline }
Denn "getline" liest einfach die nächste Zeile ein. Einmal zu Beginn aufgerufen, verschluckt es die erste Zeile...
 
Alternativ ganz profan auf der Shell die Eingabeparameter anpassen:
Code:
ls -l |tac | head -n-1 | tac | YOURAWK-SCRIPT
das 2. tac kann auch wegfallen, wenn die Reihenfolge irrelevant ist.


BTW: was hast Du für eine ls -l Ausgabe? bei mir fangen die Dateinamen in $8 an...
 
Also so sieht es jetzt aus:
Code:
#! /bin/bash

ls -l | awk '
{
        if ( NR == 1 )
        {
                next
        }
        printf ("%s ", $1)
        for ( name=9; name<=NF; name++ )
        {
                printf ("%s ", $name)
                printf("\n")
                total= total + $5
        }

}

END { print "Gesamt = " total } '
Die anderen Versionen klappten auch, aber diese Lösung passt besser in mein Konzept ;-) Danke an alle.
@TeXpert Mein ls -l sieht so aus:
Code:
-rw-r--r-- 1 stefan Domainusers   31 Nov 29 11:23 daten-for
-rwxr--r-- 1 stefan Domainusers  146 Nov 29 11:31 for-test.awk
-rw-r--r-- 1 stefan users        357 Nov 28 10:20 laender
-rw-r--r-- 1 stefan users         53 Nov 28 15:51 laender-awk
-rw-r--r-- 1 stefan users         80 Nov 28 10:21 laender-skript
-rw-r--r-- 1 stefan users       1208 Nov 28 10:50 mail
-rwxr--r-- 1 stefan users        192 Nov 28 16:33 outpass
-rwxr--r-- 1 stefan users        221 Nov 29 15:59 pls.awk
-rw-r--r-- 1 stefan users         51 Nov 26 11:38 sed1-script
-rw-r--r-- 1 stefan users         59 Nov 26 11:33 sed1-text

----1-------2----3---------4--------------5----6----7------8--------9-------
Also doch 9 ;-)
 
stka schrieb:
Also so sieht es jetzt aus:
Noch ein paar Gedanken:
Hast du schon mal ausprobiert, was passiert, wenn eine Datei wirklich ein space im Namen hat? Du zählst deren Größe doppelt und gibst sie in mindestens zwei Zeilen aus...
Zum zweiten könnte das mit den Spalten ein Problem geben, wenn eine Datei zwei spaces hintereinander im Namen hat. Diese werden von awk verschluckt.
 
So als erste Zeile weglassen hätte ich noch "| sed 1d |" Mit weniger als 6 Zeichen => "sed 1d" findet ihr nichts ;-)

Zu dem "9" Felder: schau dir mal die Situation bei einem "symbolic link" an.
Wenn definiert ist "nur Dateiname" muss evtl. das hinter "->" wech.

Zum Format: ich persönlich würde eher mit "ls -l | cut -c1-11,55-" arbeiten. Ist unabhängiger von der Felderzahl...

Haveaniceday
 
@ notoxp
Du hast recht mit den Leerzeichen. Ich finde die Art und Weise das Problem anzugehen auch nicht gut, aber das ist eine Aufgabe aus einer Schulungsunterlage, die Lösung die dort vorgegeben wir ist erstrecht falsch und da ich nächste Wochen nicht einfach sagen kann geht nicht will ich versuchen eine halbwegvernünftige Lösung nur mit awk zu basteln. Das nur mal als Hintergrund des ganzen.
 
haveaniceday schrieb:
So als erste Zeile weglassen hätte ich noch "| sed 1d |" Mit weniger als 6 Zeichen => "sed 1d" findet ihr nichts ;-)
So ein Mist! "tail +2" ist genau ein byte länger. Aber wahrscheinlich performanter... :wink:
Zum Format: ich persönlich würde eher mit "ls -l | cut -c1-11,55-" arbeiten. Ist unabhängiger von der Felderzahl...
Hmmm, da kriegst du wieder probleme bei großen Dateien im 100MB-Bereich. Lange User- und Gruppenamen könnte man mit ls -lgo ausblenden. Gar nicht so einfach, an alles zu denken...
 
stka schrieb:
Also so sieht es jetzt aus:
@TeXpert Mein ls -l sieht so aus:
Code:
-rw-r--r-- 1 stefan Domainusers   31 Nov 29 11:23 daten-for

----1-------2----3---------4--------------5----6----7------8--------9-------
Also doch 9 ;-)
und da steht auch gleich das Problem :) das Datum ist leider nicht Portabel das hängt stark von der locale ab (und evtl. noch von anderen Punkten...) bei meinem Sarge mit locale de_DE@euro ist das Datum bei ls standardmäßig auf: 2005-11-29 :) und dann knallts unter Umständen :)


ein paar kleine Verbesserung noch:
:arrow: awk hat ja zum Glück die Vorbedingungen :) -> (NR>1) als Bedingung
:arrow: printf ("%s ", $1) ist das gleiche wie "print $1"
:arrow: fehler im Algo: Dein Total wird mehrfach summiert, wenn Leerzeichen im namen sind"
:arrow: und dann Optisch, gefallen mir die 2-zeilen Ausgaben nicht ;)

Code:
ls -l | awk '
(NR>1) {
        namestr=""
        for ( name=9; name<=NF; name++ )
                namestr=namestr $name;
        total= total + $5;
        print $1, namestr;
}
END { print "Gesamt = " total } '

@notoxp: Du hast recht :) den Schwanz verdränge irgendwie immer :)

und noch zu den langen Namen (user/Gruppe), hier bietet sich an, mit ls -ln zu arbeiten, dann werden die Ids ausgegeben :)
 
TeXpert schrieb:
Code:
ls -l | awk '
(NR>1) {
        namestr=""
        for ( name=9; name<=NF; name++ )
                namestr=namestr $name;
        total= total + $5;
        print $1, namestr;
}
END { print "Gesamt = " total } '
Bleibt nur noch das Problem mit den "Zwei spaces hintereinander". Da ich nicht ganz der awk-freak bin, folgende Frage: Wie würdest du das lösen?
 
notoxp schrieb:
Bleibt nur noch das Problem mit den "Zwei spaces hintereinander". Da ich nicht ganz der awk-freak bin, folgende Frage: Wie würdest du das lösen?

k.A. da muss man IMHO dann das Parsen selber erledigen, denn der normale Trenner ist ja " ". nur bei einem Null-Trenner kommt man an die einzelnen Zeichen... das Problem ist ja auch, selbst ein ls -lQ hilft bei einem "foo bar" nicht, da das eine Feld zu einem '"foo' und das 2. zu einem 'bar"' wird :(

ich denke in dieser Situation würde ich nicht ausschließlich mit awk arbeiten wollen.
 
So wäre mein Vorschlag.
Code:
ls -l | awk '
(NR>1) {
        namestr="$9"
        for ( name=10; name<=NF; name++ )
                namestr=namestr " " $name;
        total= total + $5;
        print $1, namestr;
}
END { print "Gesamt = " total } '

Alternativ $1="" $2="" ... $8="" und die ersten acht Leerzeichen von "$0" abschneiden.
Oder über "position=index($0,$9)" rausfinden wo $9 liegt und dann mit substr($0,position) ausschneiden.
Oder...
Haveaniceday
 
Oben