Unix Shell: wyłączanie dopasowywania nazw plików w pętlach
Opublikował siefca
Pytanie
Mam w skrypcie powłoki pętlę, która iteruje po podanych jej nazwach. Reprezentują one pewne ścieżki w systemie plików. Niestety, gdy w którejś wartości znajdzie się znak gwiazdki, to przemądrzały shell w jej miejsce wstawia nazwy istniejących zbiorów pasujące do wzorca. A ja potrzebuję przekazać te gwiazdki i znaki zapytania do zmiennej, w nienaruszonej postaci.
Odpowiedź
Większość powłok próbuje nam pomóc i w przypadku pętli for … in … w miejsce nazw z listy po prawej stronie wstawia nazwy plików pasujące do symboli wieloznacznych (takich jak * czy ?).
W związku z tym wykonanie na przykład takiego kodu:
#!/bin/sh EXCLUDES="/tmp /mnt/*" for i in ${EXCLUDES} do eline="${eline} --exclude ${i}" done echo "${eline}"
Ustawi zmienną $eline na przykład na:
--exclude /tmp --exclude /mnt/cdrom --exclude /mnt/floppy
Symbol wieloznaczny * doklejony do /mnt/ został przez powłokę zinterpretowany tak, jakby podany łańcuch znaków był wzorcem dopasowania ścieżki w systemie plików. W efekcie pasujące do wzorca nazwy zbiorów zostały kolejno podstawione do zmiennej $i.
Rozwiązanie jest bardzo proste i wymaga użycia wcześniej polecenia wewnętrznego set -f. Poinstruuje ono interpreter, że ma się powstrzymać od zbawiania na siłę naszego skryptu. Po bloku przetwarzającym listy nazw możemy przywrócić domyślne zachowanie pisząc set +f.
Na przykład:
#!/bin/sh EXCLUDES="/tmp /mnt/*" set -f for i in ${EXCLUDES} do eline="${eline} --exclude ${i}" done set +f echo "${eline}"
Bardzo miłe i przydatne…