Portál AbcLinuxu, 5. května 2025 21:47

Dotaz: bash - načtení názvu souboru & zpracování

30.5.2018 14:02 Tomas96
bash - načtení názvu souboru & zpracování
Přečteno: 325×
Odpovědět | Admin
Ahoj,

lámu si hlavu s jednou zvláštností v bash (nebo spíš jsem nepochopil jak bash to bash zpracovává). Potřeboval bych načíst všechny soubory ve složce, uložit si je do arrey a pak je nadéle v cyklu nějak zpracovávat.

Takhle to funguje:

list="$(ls)"

for file in "$list"

do

rm -r "$file"

done

Já bych, ale potřeboval načíst pouze soubory a né složky. Takže bych rád místo načtení souboru použil find - nicméně takhle to nefunguje:

list="$(find -maxdepth 1 -type f)"

for file in "$list"

do

rm -r "$file"

done


Řešení dotazu:


Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

Josef Kufner avatar 30.5.2018 14:16 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: bash - načtení názvu souboru & zpracování
Odpovědět | | Sbalit | Link | Blokovat | Admin
find -maxdepth 1 -type f -exec rm -f -- {} +
nebo
find -maxdepth 1 -type f -print0 | xargs -0 rm -f
Pokud chceš něco složitějšího, tak sáhni po vhodnějším nástroji, než je Bash. Ušetříš si spoustu času a trápení. Tvůj "$list" totiž není pole ale jeden string. Když nenapíšeš uvozovky, tak for bude procházet jednotlivé části toho stringu oddělené $IFS (defaultně mezery), což znamená, že názvy souborů s mezerou se rozpadnou.
Hello world ! Segmentation fault (core dumped)
30.5.2018 19:17 Kit | skóre: 45 | Brno
Rozbalit Rozbalit vše Re: bash - načtení názvu souboru & zpracování
Odpovědět | | Sbalit | Link | Blokovat | Admin
Načítání seznamu souborů do proměnné je také zvláštnost. Sice to jde, ale obvykle se tento přístup nepoužívá, protože v tom jsou jisté záludnosti. Vždyť adresář je také seznam, tak proč ho nechceš využít k tomuto účelu? Je to mnohem jednodušší a přehlednější.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
30.5.2018 19:43 Andrej | skóre: 51 | blog: Republic of Mordor
Rozbalit Rozbalit vše Re: bash - načtení názvu souboru & zpracování
Odpovědět | | Sbalit | Link | Blokovat | Admin

Zmiňuješ pole, ale ve svém skriptu žádné pole nepoužíváš. Proto mi není jasné, co přesně nefunguje. Doporučuji přečíst si kapitolu o polích v manuálové stránce Bashe.

Následuje varianta tvého skriptu s opravdovým polem, která je ovšem (stejně jako původní skript) velmi špatný nápad, protože nepodporuje soubory s mezerami v názvech. Chybně je rozdělí na několik prvků pole.

list=($(find -maxdepth 1 -type f))
for file in "${list[@]}"; do
  rm "$file"
done

Mimochodem, je škoda nevyužít faktu, že rm přijímá víc argumentů:

rm "${list[@]}"

Tohle^^^ je ale taky svým způsobem špatně, protože to nebude fungovat, pokud celková délka názvů souborů překročí limit pro velikost pole argv na dané platformě. Proto je lepší použít find ... -exec ... {} +, jak už tu bylo řečeno — tam tento problém nenastane.

Snad ještě doplním, že budeme-li striktně trvat na poli, samozřejmě existuje i možnost správně podporovat mezery:

readarray -t list < <(find -maxdepth 1 -type f)
for file in "${list[@]}"; do
  rm "$file"
done

Tohle^^^ ale selže pro soubory, které mají v názvu konec řádku. Takové soubory bohužel můžou klidně existovat, čistě teoreticky. Například:

touch '
'

Proto je v podstatě jedinou korektní variantou něco na způsob find ... -print0 .... Nebo to celé napsat v jazyce, který důsledně rozlišuje mezi kódem a obsahem proměnných; Bash bohužel míchá obojí dohromady.

30.5.2018 22:49 Semo | skóre: 45 | blog: Semo
Rozbalit Rozbalit vše Re: bash - načtení názvu souboru & zpracování
Odpovědět | | Sbalit | Link | Blokovat | Admin
arr=( * )
for f in "${arr[@]}"; do
  [[ -f $f ]] && rm -- "$f"
done
A kvoli poradiu expanzie (vid man bash) to riesi aj medzery v nazvoch suborov a ine veci. Newliny v nazvoch suborov sice nie, ale kto ich pouziva, tak si za to sam moze.
If you hold a Unix shell up to your ear, you can you hear the C.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.