staging.inyokaproject.org

head kürzt Variable nicht

Status: Ungelöst | Ubuntu-Version: Xubuntu 16.04 (Xenial Xerus)
Antworten |

Fried-rich

Anmeldungsdatum:
2. Mai 2013

Beiträge: 1162

Hallo,

folgendes Skript:

for i in ordner ; do
 a=$(dirname "$i" | head -n 1)
 echo $a
done

Mir werden hier alle Pfade der Dateien in dem Ordner angezeigt. Ich dachte aber mit head das ganze auf die 1. Zeile begrenzen zu können. Wieso geht das hier nicht? Es kommt keine Fehlermeldung zu head. Das ganze geht wenn ich z. B. die Ausgabe in eine Datei leite und dann

head -n 1 datei

ausführe.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Mir ist unklar was das werden soll. Ohne Wildcards dürfte

1
for i in ordner 

nichts weiter liefern als eben ordner - wozu also iterieren?

1
a=$(dirname ordner)

müsste doch das gleiche liefern, oder?

Womöglich musst Du einen Ausschnitt der Ordnerstruktur zeigen, und was Du als Ausgabe haben möchtest.

Fried-rich

(Themenstarter)

Anmeldungsdatum:
2. Mai 2013

Beiträge: 1162

Ordner steht für einen x-beliebigen Ordner in dem sich Dateien befinden.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Und was gibt

1
2
3
for i in ordner ; do
  echo $i
done

aus?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@Fried-rich: Die Laufvariable enthält einen Dateinamen (falls ordner so aussieht, das tatsächlich über alle Dateinamen in dem Ordner iteriert wird). Wie soll also ein head innerhalb der Schleife, das auf die Verarbeitung des jeweils aktuellen Dateinamens angewendet wird, irgendeinen Einfluss auf die globbing-Expansion im Schleifenkopf haben‽ Das head bezieht sich auf die Ausgabe von dirname "$i", denn das ist genau das was da steht. Das sieht so ein bisschen nach „ich wünsche mir jetzt ganz doll, dass das etwas anderes bedeutet als es das normalerweise tut“ aus. Funktioniert leider nicht. Rechner machen immer nur was man ihnen sagt, nicht was man eigentlich meinte oder gerne hätte. 😉

Du könntest die Schleife am Ende des Schleifenkörpers mit exit verlassen. Dann wird nur der erste Dateiname verarbeitet. Wobei Du dann noch mal nachdenken müsstest ob das tatsächlich auch immer der ist, den Du gerne hättest.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Mach doch mal, und zeig uns die Ausgabe von:

1
2
3
4
5
6
for i in ordner ; do
   echo i $i
   echo dirname i $(dirname "$i") 
   a=$(dirname "$i" | head -n 1)
   echo $a
done

Gerne mit einem Testordner mit wenigen Daten, aber genug, um jedem Befehl was zu tun zu geben.

Fried-rich

(Themenstarter)

Anmeldungsdatum:
2. Mai 2013

Beiträge: 1162

@ user_unknown

Da kommt

i /media/daten1/test/001.jpg
dirname i /media/daten1/test
/media/daten1/test
i /media/daten1/test/002.jpg
dirname i /media/daten1/test
/media/daten1/test
i /media/daten1/test/003.jpg
dirname i /media/daten1/test
/media/daten1/test
i /media/daten1/test/004.jpg
dirname i /media/daten1/test
/media/daten1/test
i /media/daten1/test/005.jpg
dirname i /media/daten1/test
/media/daten1/test

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@Fried-rich: Und wie unterscheidet sich /media/daten1/test von dem was Du für ordner tatsächlich im Quelltext stehen hast? Und welchen Sinn macht diese Schleife dann?

Fried-rich

(Themenstarter)

Anmeldungsdatum:
2. Mai 2013

Beiträge: 1162

Ich will doch einfach nur wissen wieso hier head nicht so geht wie es soll. Das war eine x-beliebige Schleife die ich am erstbesten Ordner ausprobiert hab. Es gibt kein konkretes Vorhaben was ich hier umsetzen will. Hab einfach einen Ordner mit Bildern genommen. Das Problem mit head in einer Schleife hatte ich schon ein paar mal und es irgendwie anders hingebogen aber nie verstanden wieso es nicht geht.Daher war das 1. Bsp. auch so allgemein gehalten.

'Ordner' steht einfach für jeden x-beliebigen Ordner. Nicht mehr, nicht weniger.

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7795

Nimm die Befehle doch mal einzeln.

$ dirname was/ist/denn/hier/los
was/ist/denn/hier

dirname mit einem Argument gibt eine Zeile aus. Wenn keine Leerzeichen im Pfad sind, auch nur ein Wort.

$ dirname was/ist/denn/hier/los | head -n 1
was/ist/denn/hier

head -n 1 gibt die erste Zeile aus. Da dirname sowieso nur eine Zeile ausgegeben haben kann (wenn man mal von Zeilenumbrüchen in Dateinamen absieht), bleibt die Ausgabe unverändert.

Das echo danach gibt dann auch genau das aus, was dirname ausgegeben hat. Wenn du hier mehr als eine Zeile Ausgabe bekommst, dann ist es die for-Schleife drum herum, die eben mehrfach durchlaufen wird.

Ich will doch einfach nur wissen wieso hier head nicht so geht wie es soll.

Es kann keiner beantworten weil kein Mensch weiß, was du hier für ein Ergebnis erwartest.

Und dein Beispielscript ist soweit verfälscht daß man es da auch nicht herauslesen kann.

Das Problem mit head in einer Schleife hatte ich schon ein paar mal und es irgendwie anders hingebogen aber nie verstanden wieso es nicht geht.

Irgendein grundlegendes Missverständnis scheint vorzuliegen, ich weiss leider nicht welches.

Mit 'set -x' kannst du die Shell in den Debugmodus kicken, da wird jeder ausgeführte Schritt einzeln ausgegeben. Manchmal hilft das mit dem Verständnis. Ansonsten eigene Debugmeldungen nach Bedarf einbauen.


Eine Anmerkung noch zum echo $a. Hast du vielleicht Sternchen im Dateinamen? Oder tatsächlich for x in "*" geschrieben?

$ a="*"
$ echo $a
datei1 datei2 datei3 datei4
$ echo "$a"
*

Das wär dann ein klassischer Fall von - falsch gequotet.

Aber das ist jetzt wild geraten denn in deinem Beitrag steht das so nicht drin...

Bei Variablen gehören meistens "" drum herum. Bei * meistens nicht, wenn es für "alle Dateien" stehen soll.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Bei mir kommt für einen nichtleeren Ordner "filter":

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
t201:~/proj/mini/forum > l filter
insgesamt 144
drwxr-xr-x  5 stefan stefan  4096 Aug  7  2008 .
drwxr-xr-x 21 stefan stefan 49152 Mär 29 23:57 ..
drwxr-xr-x  3 stefan stefan  4096 Aug  7  2008 classes
drwxr-xr-x  4 stefan stefan  4096 Aug  7  2008 filter
-rw-r--r--  1 stefan stefan  4287 Aug  7  2008 filter.jar
-rw-r--r--  1 stefan stefan    34 Aug  7  2008 filter.manifest
-rw-r--r--  1 stefan stefan   114 Aug  7  2008 machjar
-rw-r--r--  1 stefan stefan    18 Aug  7  2008 semi.dat
drwxr-xr-x  3 stefan stefan  4096 Aug  7  2008 src
-rw-r--r--  1 stefan stefan    18 Aug  7  2008 test.dat
-rw-r--r--  1 stefan stefan   178 Aug  7  2008 test.sh

Wenn ich Deine Schleife eingebe:

1
2
3
4
5
t201:~/proj/mini/forum > for i in filter 
do
   echo $i; 
done
filter

Nur das Wort filter raus. Vielleicht ist da ja eine Globbingeinstellung unterschiedlich, oder Du hast nicht ordner in Deinem Script stehen, oder Du benutzt eine andere Shell.

Dagegen kommen hier mehr Daten

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
for i in filter/* ; do   echo $i; done
filter/classes
filter/filter
filter/filter.jar
filter/filter.manifest
filter/machjar
filter/semi.dat
filter/src
filter/test.dat
filter/test.sh

Die aber durch dirname wieder eingedampft werden, auf das, was wir schon wussten:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
for i in filter/* ; do   echo $(dirname $i); done
filter
filter
filter
filter
filter
filter
filter
filter
filter

Die Zahl der Dateien könnten wir so zählen.

Wenn uns das alles zu viel ist, dann können wir head hinter die Schleife bauen:

1
2
for i in filter/* ; do   echo $(dirname $i); done | head -n 1
filter

Beispiele mit sinnlosen Daten sind prima, da macht man nichts kaputt. Aber ein Code, der - egal wie die Daten liegen - immer nur das Verzeichnis ausgibt, das man vorher schon kannte - das taugt höchstens dazu zu prüfen, ob for/echo/dirname/head nicht kaputt sind.

Die Testdaten müssen schon so komplex sein, dass das Ergebnis nicht erraten werden kann, ohne Dein Verzeichnis zu kennen:

1
2
for i in filter/*/* ; do   echo $(dirname $i); done | head -n 1
filter/classes

Und die Wildcards zu verschweigen, wenn wir mehrfach danach fragen - wir wollen nicht Deine Festplatte ausspähen, und dafür müssen wir eben wissen, was Du gemacht hast.

Antworten |