V ideálním případě to tak neděláte vůbec, protože správně analyzovat názvy souborů ve skriptu shellu je vždy obtížné (opravte mezery, stále budete mít problémy s jinými vloženými znaky, zejména s novým řádkem). Toto je dokonce uvedeno jako první položka na stránce BashPitfalls.
To znamená, že existuje způsob, jak téměř dělat to, co chcete:
oIFS=$IFS
IFS=$'\n'
find . -name '*.txt' | while read -r i; do
# use "$i" with whatever you're doing
done
IFS=$oIFS
Nezapomeňte také uvést $i
při jeho používání, aby se předešlo dalšímu výkladu mezer později. Nezapomeňte také nastavit $IFS
zpět po jeho použití, protože pokud tak neučiníte, způsobí to později matoucí chyby.
K tomu je připojeno ještě jedno upozornění:co se děje uvnitř while
smyčka se může odehrávat v podskořápce v závislosti na přesném prostředí, které používáte, takže nastavení proměnných nemusí přetrvávat. for
smyčková verze se tomu vyhýbá, ale za cenu, že i když použijete $IFS
řešení, abyste se vyhnuli problémům s mezerami, budete mít potíže, pokud find
vrací příliš mnoho souborů.
V určitém okamžiku se správnou opravou pro toto vše stane provádění v jazyce, jako je Perl nebo Python místo shellu.
Použijte find -print0
a přesuňte jej na xargs -0
, nebo napište svůj vlastní malý program v C a přeneste ho do svého malého programu v C. To je to, co -print0
a -0
byly vynalezeny pro.
Shell skripty nejsou nejlepší způsob, jak zacházet s názvy souborů s mezerami:můžete to udělat, ale je to neohrabané.
Můžete nastavit "vnitřní oddělovač polí" (IFS
) na něco jiného než prostor pro rozdělení argumentu smyčky, např.
ORIGIFS=${IFS}
NL='
'
IFS=${NL}
for i in $(find . -name '*.txt'); do
IFS=${ORIGIFS}
#do stuff
done
IFS=${ORIGIFS}
Resetoval jsem IFS
po jeho použití v nálezu, většinou proto, že vypadá hezky, myslím. Nezaznamenal jsem žádné problémy s nastavením na nový řádek, ale myslím, že je to "čistší".
Další metoda, v závislosti na tom, co chcete dělat s výstupem z find
, je buď přímo použít -exec
s find
nebo použijte -print0
a potrubím do xargs -0
. V prvním případě find
postará se o escapování názvu souboru. V -print0
případ, find
vytiskne svůj výstup s oddělovačem null a poté xargs
se v tomto rozchází. Protože žádný název souboru nemůže obsahovat tento znak (co já vím), je to také vždy bezpečné. To je většinou užitečné v jednoduchých případech; a obvykle není skvělou náhradou za úplné for
smyčka.