Stwórzmy katalog ze znakiem końca wiersza w środku jego nazwy. Dla odmiany po poprzednim wpisie użyjmy Perla.
linux$ perl -e 'mkdir("prefix\nsuffix")'
Co możemy powiedzieć o naszym dziele?
linux$ ls
prefix?suffix
linux$ ls | cat
prefix
suffix
Wygląda podejrzanie. Ma to pewne implikacje nie tylko dla mechanizmu autouzupełniania powłoki :) ale także dla innych aplikacji:
linux$ find . -type d -name 'prefix*' | xargs rmdir
rmdir: nie udało się usunąć `./prefix': Nie ma takiego pliku ani katalogu
rmdir: nie udało się usunąć `suffix': Nie ma takiego pliku ani katalogu
Po to właśnie wymyślono opcję użycia znaku NULL jako separatora wierszy:
linux$ find . -type d -name 'prefix*' | xargs printf "received [%s]\n"
received [./prefix]
received [suffix]
linux$ find . -type d -name 'prefix*' -print0 | xargs -0 printf "received [%s]\n"
received [./prefix
suffix]
Teraz już możemy bezpiecznie i skutecznie usunąć katalog.
linux$ find . -type d -name 'prefix*' -print0 | xargs -0 rmdir
linux$ ls
linux$
Na marginesie: spotkałem się kiedyś z komercyjnym UNIX-em, który zwyczajnie nie wspierał takich opcji w
find
i xargs
. :)Wniosek z tego płynie taki: jeśli przetwarzasz wynik dowolnych poleceń zwracających nazwy plików, lepiej nie polegaj na znaku końca wiersza jako faktycznym znaczniku końca linii. Możesz ryzykować nie tylko załamaniem procesu przetwarzania, ale także stworzyć zagrożenie.
Co by się stało, gdybyśmy tu mieli
xargs rm -rf
?
linux$ perl -e 'mkdir("prefix\n..")'
linux$ find . -type d -name 'prefix*' | xargs printf "received: [%s]\n"
received: [./prefix]
received: [..]
Potrzeba czujności nie dotyczy tylko skryptów powłoki, ale także np. logów. Wiele aplikacji prowadzi logi tekstowe, które parsuje się później wiersz po wierszu. Jeśli aplikacja wpisuje do loga nazwę pliku, może się okazać, że ten konkretny wpis został podzielony na wiele wierszy. Tego typu zachowanie zaobserwowałem kiedyś w logach serwera aplikacyjnego JEE: aplikacja przetwarzała pliki ze spoola i odkładała w logach ślad swojej pracy, w tym nazwę otwieranego pliku.
Brak komentarzy:
Prześlij komentarz