2013-02-25 14 views

Odpowiedz

97

Tutaj jest lepszy sposób na pętli na plikach, ponieważ obsługuje on spacje i znaki nowej linii w nazwach plików:

find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do 
    echo "$line" 
    ls -l "$line"  
done 
+9

+1 To nie jest tylko lepsze, to prawda. – chepner

+0

Mam problem z uruchomieniem tego, gdy skrypt zawierający ten fragment zostanie wywołany z cronjob @reboot. Składa skargę na flagę -d polecenia read, a następnie nie uruchamia się. W przeciwnym razie działa świetnie. –

+8

Działa na bash, nie na sh. – Antzi

5

Korzystając command substitution zamiast cytatów wykonać polecenie find zamiast przekazać polecenie jako ciąg znaków:

for line in $(find . -iname '*.txt'); do 
    echo $line 
    ls -l $line; 
done 
+1

jeśli masz plik o nazwie "pojedynczy plik", otrzymasz dwa '$ linie' w pętli. Jeden dla "pojedynczego" innego dla "pliku". – gcb

18

The for -loop będzie iterować po każdym (oddzielonym spacjami) wpisie na podanym łańcuchu.

Nie wykonujesz komendy find, ale podajesz ją jako ciąg (który jest iterowany przez for-loop). Zamiast cudzysłów użyć albo odwrócone, pojedyncze apostrofy lub $():

for line in $(find . -iname '*.txt'); do 
    echo "$line" 
    ls -l "$line" 
done 

Ponadto, jeśli ścieżki dostępu do plików/nazwiska zawiera spacje ta metoda zawiedzie (od for -loop iteruje przestrzeni wydzielonych zgłoszeń). Zamiast tego lepiej użyć metody opisanej w dogbanes answer.


Aby wyjaśnić swój błąd:

Jak powiedział for line in "find . -iname '*.txt'"; iteracje nad całą przestrzeń oddzielona wpisów, które są:

  • znaleźć
  • .
  • -iname
  • „* .txt” (chyba ...)

Pierwsze dwa nie powodują błędu (oprócz niepożądanego zachowania), ale trzeci jest problematyczne, ponieważ wykonuje :

ls -l -iname 

wiele poleceń (bash) może łączyć opcje pojedynczego znaku, więc -iname jest taka sama jak -i -n -a -m -e. I voila: twój błąd invalid option -- 'e'!

+9

Jeśli w nazwie są spacje, pojawią się one jako dwa oddzielne wpisy na liście, które pętla for przechodzi z iteracją. – chepner

12

Bardziej zwarta wersja działa ze spacjami i znakami nowej linii w nazwie pliku:

find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \; 
+0

Ta odpowiedź jest znacznie prostsza i działa zarówno w Bashu, jak i prostsze muszle sh (jesionowe). – Alkaline

Powiązane problemy