Nowe posty

Autor Wątek: grep -l ?  (Przeczytany 3372 razy)

SwIeRsZcZ

  • Gość
grep -l ?
« dnia: 2009-03-07, 23:29:00 »
w katalogu mam różne foldery i pliki.

chcę napisać polecenie, które wylistuje katalogi których nazwa konczy się na literę "i" oraz pliki ,których nazwy kończą się na "A" . Niestety poniższe polecenie nie działa . W czym tkwi błąd ?

ls -l | grep -l A$ | grep i$

Offline ultr

  • Users
  • Guru
  • *****
  • Wiadomości: 1177
    • Zobacz profil
grep -l ?
« Odpowiedź #1 dnia: 2009-03-08, 01:24:39 »
> grep -l A$

Aby grep rozpoznawał wyrażenia regularne, wymaga parametru -e.

Poza tym odradzam używać grepa tam, gdzie nie porównujesz całej linii, ale tylko jej fragment. Znacznie lepiej użyć wtedy awk. Tu teoretycznie można to obejść używając "ls -1".


> ls -l | grep -l A$ | grep i$

Poza tym z tego co napisałeś wygląda, że masz wylistować 2 różne rzeczy (łączenie OR). Twoje polecenie działa jak łączenie logicznym AND.

Pominąłeś też fragment, że jedna lista ma być katalogami, a druga plikami. ls nie pozwoli ci na taką selekcję. Ale find już tak.


Po prostu połącz 2 odpowiednie polecenia find za pomocą średnika. Find wystarczy wywołać w aktualnym katalogu (.), określić nazwę pliku i jego typ. Watro też podać na jaką głębokość ma przeszukiwać podkatalogi (jeśli chcesz tylko te z aktualnego katalogu, to ustawiasz 0).
Odsyłam do `man find` (PL), tam są te i inne parametry dobrze wyjaśnione.

arctgx

  • Gość
grep -l ?
« Odpowiedź #2 dnia: 2009-03-08, 01:26:34 »
Żeby uniknąć aliasów dla ls wywołajmy je jako /bin/ls, pokazując przy okazji przykład:
  rip $ /bin/ls -l
razem 8
drwxr-xr-x 2 arctgx arctgx 4096 mar  8 00:46 boczek
drwxr-xr-x 2 arctgx arctgx 4096 mar  8 00:44 kości
-rw-r--r-- 1 arctgx arctgx    0 mar  8 00:46 talerz
-rw-r--r-- 1 arctgx arctgx    0 mar  8 00:45 trumnA
Aliasy mogłyby wywołać ls z opcją dającą gwiazdki, ukośniki czy inne dziwne znaki na końcu linii. Jakkolwiek ukośnik przydałby się tu, to z plikami już gorzej. Zamiast ukośnika wykorzystamy d na początku dla katalogów.

Skąd wzięła Ci się opcja -l w grep? Nie filtrujesz przecież plików tylko standardowe wyjście polecenia ls. To co robisz, jest powiedzeniem, by wyszukać linie kończące się na A, a potem wśród nich wyszukać linie kończące się na i, czyli zbiór pusty w efekcie ;)

Spójrzmy na jedno z podejść:
  rip $ /bin/ls -l | grep -E '^-.*A$|^d.*i$'
grep: błędna opcja -- .
Składnia: grep [OPCJA]... WZORZEC [PLIK] ...
Napisz `grep --help' żeby dowiedzieć się więcej.
Celowo wrzuciłem z błędem. Kreska w wyrażeniu regularnym grepa została przechwycona przez (niech ktoś dopisze czy grepa, powłokę, czy może jakąś funkcję systemową GNU) ... jako początek kolejnej opcji. Żeby nie interpretować kreski w ten sposób, trzeba wskazać grepowi miejsce, gdzie kończą się opcje i kreska ma być interpretowana dosłownie:
  rip $ /bin/ls -l | grep -E -- '^-.*A$|^d.*i$'
drwxr-xr-x 2 arctgx arctgx 4096 mar  8 00:44 kości
-rw-r--r-- 1 arctgx arctgx    0 mar  8 00:45 trumnA
A teraz słowo o tym, co znaczą kawałki. Żeby użyć alternatywy (|), skorzystałem z rozszerzonych wyrażeń regularnych (opcja -E). No i masz dwa wyrażenia, w których pomiędzy znakiem początku i końca linii występuje co trzeba.

Jedno ciche założenie: Twoje "pliki" rozumiałem jako zwykłe pliki.

P.S. Jeszcze do @ultra, który zdążył mnie wyprzedzić :) Pomysł z findem powinien zmieścić się w jednym poleceniu (zobacz spójnik -o).

SwIeRsZcZ

  • Gość
grep -l ?
« Odpowiedź #3 dnia: 2009-03-08, 12:33:46 »
Mam jeszcze pytanie co do polecenia find. Rozumiem że przy jego użyciu nie mogę stosować wyrażeń regularnych jak w grepie, nie mogę znaleźć np. katalogu którego nazwa kończy się na 'y' albo pliku z początkową literą 'F' ?

find . -name 'Nowy'; find . -type f -name "Firma.*"
coś takiego nie przejdzie ?

find . -name '$y'; find . -type f -name '^F'

arctgx

  • Gość
grep -l ?
« Odpowiedź #4 dnia: 2009-03-08, 14:18:54 »
Wprawdzie istnieje opcja -regex (zobacz man -L C find, nie wiem jak w polskim manualu), ale zdaje się, że odpowiedź na Twoje pytanie powinna obyć się bez nich: po prostu -type d -name "*y" albo -type f -name "F*". Przy kombinowaniu warunków nie zapomnij o nawiasach i kolejnościach wykonywania działań (zob. ten wątek: http://forum.linux.pl/viewtopic.php?id=13216 ).