m.g.o.d
Anmeldungsdatum: 18. November 2019
Beiträge: 29
|
Hi Zusammen, ich habe einen ganz einfachen Bashskript Code, wo ich nicht verstehe, wieso ich das Array nicht einzeln ausgeben kann: | #! /bin/bash
cd /home/marc/Scripts
array=$(find *.txt) #Ausgabe next.txt test.txt third.txt
for count in ${array[@]} #creating array
do
echo ${count[@]} #Funktioniert!
echo ${array[2]} #funktioniert nicht...
done
|
Ich kann mir mit echo den Inhalt der Suche ausgeben lassen. Aber wenn ich z.B. sage echo "${array[2]} ", dann passiert nix. Auf pos.2 muss definitiv ein Suchergebnis stehen (–> third.txt). Was mache ich falsch? Besten Gruß,
Marc
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Hallo! Zum nutzt du die Schleife nicht sinnvoll: | for count in $array; do
echo $count
done
|
Dann ergibt dein find kein array, bzw. nur 1 Element im Array. Du müsstest also anders vorgehen, um die Dateien als array einzulesen.
| #!/bin/bash
oldIFS=$IFS
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -iname "*.txt" -print0)
IFS=$oldIFS
echo "${array[2]}"
|
Aber warte mal auf die Bashjungs… ich kann das auch nur so aus meinen Scripts raus zeigen ☺
|
m.g.o.d
(Themenstarter)
Anmeldungsdatum: 18. November 2019
Beiträge: 29
|
Achso das heisst die 3 Ergebniss, die find liefert, sind für das Array nur ein einziges Feld? Dann wäre die Frage, wie ich die 3 Ergebnisse von Find ind das Array bekomme, so das jedes Ergebnis in ein seperates Feld geschrieben wird. Puh, keine Ahnung ☹
|
mike1963
Anmeldungsdatum: 28. August 2018
Beiträge: 19
|
m.g.o.d schrieb: Achso das heisst die 3 Ergebniss, die find liefert, sind für das Array nur ein einziges Feld? Dann wäre die Frage, wie ich die 3 Ergebnisse von Find ind das Array bekomme, so das jedes Ergebnis in ein seperates Feld geschrieben wird. Puh, keine Ahnung ☹
Prinzipiell geht's, indem man die gesamte find-Anweisung in eine Klammer steckt, also so: |
array=( $(find . -type f) ) # array=$(find . -type f) speichert alles in EINE Variable
# Durch die äusseren runden Klammern erzwingt man die Speicherung als Array
# Testausgabe des Arrays ...
echo "${array[*]}"
|
ABER: Das funktioniert NICHT, bzw. bringt falsche Ergebnisse, wenn in irgendwelchen Dateinamen Blanks vorhanden sind ...
|
m.g.o.d
(Themenstarter)
Anmeldungsdatum: 18. November 2019
Beiträge: 29
|
mike1963 schrieb: m.g.o.d schrieb: Achso das heisst die 3 Ergebniss, die find liefert, sind für das Array nur ein einziges Feld? Dann wäre die Frage, wie ich die 3 Ergebnisse von Find ind das Array bekomme, so das jedes Ergebnis in ein seperates Feld geschrieben wird. Puh, keine Ahnung ☹
Prinzipiell geht's, indem man die gesamte find-Anweisung in eine Klammer steckt, also so: |
array=( $(find . -type f) ) # array=$(find . -type f) speichert alles in EINE Variable
# Durch die äusseren runden Klammern erzwingt man die Speicherung als Array
# Testausgabe des Arrays ...
echo "${array[*]}"
|
ABER: Das funktioniert NICHT, bzw. bringt falsche Ergebnisse, wenn in irgendwelchen Dateinamen Blanks vorhanden sind ...
Gracias! Ich probiere es nacher gleich aus. VG
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12834
|
mike1963 schrieb:
ABER: Das funktioniert NICHT, bzw. bringt falsche Ergebnisse, wenn in irgendwelchen Dateinamen Blanks vorhanden sind ...
Eben! Schlauer ist folgender Ansatz, finde ich: | find ... -exec sh -c 'for f; do
echo "$f found"
done' -- +
|
Da werden die Dateinamen auf jeden Fall korrekt übergeben. Wenn man es mit einer while -Schleife machen will, dann so (benötigt die bash , sh kennt "-d" nicht). | find ... -print0 | while -rd '' f; do echo "$f"; done
|
Das ist im Prinzip die Lösung von ChickenLipsRfun2eat, nur umgedreht und ich speichere die Namen nicht in einem Array.
| #!/bin/bash
oldIFS=$IFS
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -iname "*.txt" -print0)
IFS=$oldIFS
echo "${array[2]}"
|
Die Variable "oldIFS" ist überflüssig, denn Du setzt den "IFS" ja nur für read um: | $ foo=bar
$ echo "$foo"
bar
$ foo=123 env | fgrep foo=
foo=123
$ echo "$foo"
bar
|
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
rklm schrieb: Die Variable "oldIFS" ist überflüssig, denn Du setzt den "IFS" ja nur für read um:
Bei IFS bin ich mir nie sicher und in meinem Ramsch-Script wird der öfter umgesetzt, deswegen habe ich es drin gelassen ☺ Aber klingt logisch, bei nur einer Verwendung.rklm schrieb:
| find ... -exec sh -c 'for f; do
echo "$f found"
done' -- +
|
Find ich prima. Das hab ich mir auch gleich mal geklaut ☺
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12834
|
ChickenLipsRfun2eat schrieb: rklm schrieb:
| find ... -exec sh -c 'for f; do
echo "$f found"
done' -- +
|
Find ich prima. Das hab ich mir auch gleich mal geklaut ☺
Ich sehe gerade, da fehlt etwas Entscheidendes: | find ... -exec sh -c 'for f; do
echo "$f found"
done' -- {} +
|
Finde den Unterschied! 😉
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Der Dateiname wird nicht übergeben…
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12834
|
ChickenLipsRfun2eat schrieb: Der Dateiname wird nicht übergeben…
Die Dateinamen - aber ja. Der Poster erhält 100 Gummipunkte! ☺
|
mike1963
Anmeldungsdatum: 28. August 2018
Beiträge: 19
|
rklm schrieb: mike1963 schrieb:
ABER: Das funktioniert NICHT, bzw. bringt falsche Ergebnisse, wenn in irgendwelchen Dateinamen Blanks vorhanden sind ...
Eben! Schlauer ist folgender Ansatz, finde ich: | find ... -exec sh -c 'for f; do
echo "$f found"
done' -- +
|
...
Ich sehe gerade, da fehlt etwas Entscheidendes:
Und genau das ist der Grund, warum ich - wenn ich mir sicher bin, dass das Script nur ich verwende und, daß in den Dateinamen die ich ansprechen möchte eben kein Space vorhanden ist - die Lösung array=( $(find . -type f) ) bevorzugen würde. ☺ Mit meinen bescheidenen Bash-Kenntnissen sehe ich bei Deinem Code nicht auf den ersten Blick, was er denn eigentlich tut - und wenn ich ihn selbst schreiben möchte, müsste ich zuerst in man-pages stöbern ... Klar, Deiner ist sauberer und stabiler, er funktioniert auch bei Files die ein Space im Dateinamen haben, alles keine Frage - meiner hat für mich (!) aber den Vorteil, daß ich auf den ersten Blick sehe, was er tut. Da nehme ich in Kauf, dass er bei Files mit Space im Dateinamen (die zumindest bei mir ohnehin extremst selten sind) falsche Ergebnisse liefert. 😉
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
Eigentlich reicht da doch schon die Bash mit globstar-Option, um die *.txt Pfade in einen array zu bringen - das klappt ganz ohne Subshell und man muss sich über Whitespace in Dateinamen keine Gedanken machen: | shopt -s globstar
array=(**/*.txt)
|
Auch eine Schleife, die die Pfade direkt verarbeitet (und z.B. nach Dateien filtert) ist damit simpel:
| shopt -s globstar
for f in **/*.txt
do
[ -f "$f" ] && echo "file $f found" || continue
done
|
Das ganze ist vermutlich nicht ganz so performant wie find, aber man stolpert weniger leicht über Sonderfälle.
|