/ / struny vrátené vyhľadávaním sa oddeľujú v strede - bash, shell

reťazce vrátené vyhľadávaním sa oddeľujú v strede - bash, shell

Ja som nový skript (bash) na termináli, find sa správa ako:

find . -name "Ado*"
./Adobe ReaderScreenSnapz001.jpg
./Adobe ReaderScreenSnapz002.jpg

Zdá sa, že môj shellový skript oddeľuje názov súboru podľa medzery po "Adobe".

kód:

#!/bin/sh
i=1
for base_name in `find . -name "Ado*"`
do
echo $base_name
:
i=$((i+1))
done

Vráti sa niečo ako:

./Adobe
ReaderScreenSnapz001.jpg
:

Čo je zlé kde?

odpovede:

3 pre odpoveď č. 1

Väčšina doterajších odpovedí bola použitá find ... | while read ... ktorý funguje, ale cyklica while beží v podsvete (pretože je to súčasť potrubia), a tak sa váš počet súborov ($ i) stratí, keď sa ukončí podsveľ.Ak používate bash (t.j. musieť byť #!/bin/bash, nie #!/bin/sh), môžete použiť jeho funkciu nahradzovania procesov, aby ste predišli tomuto problému:

i=1
while IFS= read -r -u3 -d "" base_name; do
echo "$base_name"
:
i=$((i+1))
done 3< <(find . -name "Ado*" -print0)

Pridal som tu aj ďalšie triky, aby som to urobil robustnejším: nastavil som IFS na nulu (len pre príkaz na čítanie), aby sa nezostrihol vedúci alebo koniec bielych priestorov zo súborov; Používam čítanie "s -r tak to nebude robiť vtipné veci s backslash v názvy súborov, používam nájsť "s -print0 a čítaj "s -d "" používať nulové bajty ako oddeľovač súborov, takže to nebude ani zmätený linefeeds v názvoch súborov, používam dvojité kotácie okolo $base_name vo vnútri slučky, takže sa to nepodarí rozdeliť(nie je dôležité pre echo, ale bude to dôležité, ak sa skutočne pokúsite použiť názvy súborov ako názvy súborov) a napokon prechádza zoznam súborov cez fd # 3 namiesto # 0 (stdin) s 3< a čítaj "s -u3 možnosť, takže v prípade, že čokoľvek vnútri slučky číta zo stdin, nebude to náhodou inhalovať hromadu súborov.


1 pre odpoveď č. 2
find . -name "Ado*"
./Adobe ReaderScreenSnapz001.jpg
./Adobe ReaderScreenSnapz002.jpg

Na find výsledok obsahuje white-spaces.
Tak takto for loop Iterácia súboru nad 4 položky.

Môžete zmeniť skript:

i=1
find . -name "Ado*" | while read base_name
do
echo $base_name
:
i=$((i+1))
done

1 pre odpoveď č. 3

Váš shell nahradí for base_name in $(find . -name "Ado*") podľa
for base_name in ./Adobe ReaderScreenSnapz001.jpg ./Adobe ReaderScreenSnapz002.jpg

Z tohto dôvodu for vidí štyri slová:
- ./Adobe
- ReaderScreenSnapz001.jpg
- ./Adobe
- ReaderScreenSnapz002.jpg

Moja rada: nahradiť for base_name in podľa while read base_name

#!/bin/sh
i=1
find . -name "Ado*" |
while read base_name
do
echo $base_name
:
i=$((i+1))
done

read číta riadok po riadku a zastaví while opakovanie na konci jeho vstupu (find).
read Obchody v každom riadku base_name variabilné.


1 pre odpoveď č. 4

Nie je nič zlého v shell skript.

Keď zavoláte program medzi spätných úvodzoviek príkaz je vykonaný v kľukaté proces a výsledok je vrátený do hlavného programu lexed a analyzované.A ako reťazec výsledok je rozdelený do niekoľkých token.

Mali by ste použiť čítať builtin takého

#! /bin/sh
i=0
find . -name "Ado*" | while read result
do
echo $result
i=$((i+1))
done