Witam. Jest to mój pierwszy post.
Moim zadaniem jest napisanie skryptow ktory wypisze nazwy plikow z katalogu bierzacego, ktorego nazwa i tresc zawierają tekst /*main*/. oto moj niedziałajacy kod:
for i in `ls -la`
do
if [ ! -d $i ]; then
plik= `head $i`
id [ "$plik" = '/*main*/' ]; then
echo $i
echo " znalazlem plik"
fi
fi
done
1. Przygotowalem sobie przyklad , dwa pliki z czego do jednego wrzucilem
int main() { cout << "hello"; system("pause"); return 0; }
Nie wiem czy main ma byc z gwiazdkami czy bez ...
2. Odpalam skrypt
$ ./test
./test: linia 9: błąd składni przy nieoczekiwanym znaczniku `then'
./test: linia 9: ` id [ "$plik" = '/*main*/' ]; then'
3. Przyglądam się liniom pokolei
" for i in `ls -la` "
Polecenie ls -la wykonane w terminalu
$ ls -la
razem 44
drwxr-xr-x 2 tx tx 4096 maj 23 13:06 .
drwxr-xr-x 3 tx tx 4096 maj 11 16:53 ..
-rwxr-xr-x 1 tx tx 9976 maj 13 21:55 a
-rw-r--r-- 1 x tx 1237 maj 13 21:55 a.c
-rw-r--r-- 1 tx tx 1951 mar 24 2011 f.png
-rw-r--r-- 1 tx tx 8227 maj 23 13:06 ron
-rwxr-xr-x 1 tx tx 158 maj 23 13:03 test
Lepiej przyjżyj sie jak taka petla działa, a własciwie czego potrzebuje, wykonujac przyklady w terminalu
https://www.cyberciti.biz/faq/bash-for-loop/
Zróbmy sobie przyklad
#!/bin/bash
for i in `ls -la`
do
echo $i
done
Odpalmy teraz skrypt do celów testowych , a oto fragment wyniku
$ ./test
razem
44
drwxr-xr-x
2
tx
tx
4096
maj
23
13:16
.
drwxr-xr-x
3
tx
tx
4096
maj
11
16:53
..
-rwxr-xr-x
...
Wydzisz coś zrobił ? Zeby to poprawnie dzialalo byś musiał użyć komendy lub lini komend które wyswietlą tylko nazwy plików.
No to teraz naprawmy to
- stwórzmy ową komende która wyświetli tylko pliki ( wykonamy komende w terminau )
$ ls -la | grep ^"-" | awk '{printf $9 " " }'
a a.c f.png ron test
No widać działa, wyszukało tylko pliki, a po " | awk '{printf $9 " " }' " pokazuje tylko ostatnia kolumne , czyli nazwy plików
Przetestujmy to w pętli for, czyli w skrypcie
#!/bin/bash
for i in `ls -la | grep ^"-" | awk '{printf $9 " " }'`
do
echo $i
done
A oto wynik skryptu:
- skoro mamy nazwe pliku to teraz jak wyszukać w pliku jakąś nazwe ?
id [ "$plik" = '/*main*/' ]; then
Co to jest " id " ?
id
Print real and effective user id (uid)
https://ss64.com/bash/id.html
Napewno oto Ci chodziło ?
Wpisz w wyszukiwarce internetowej " linux wyszukiwanie znakow w pliku "
Dzieki znalezionym skąpym ale jednak informacjom dowiesz się że do wyszukiwania plików używa się komendy find
a do wyszukiwania w plikach grep i owe znaki w pliku to ciągi znaków.
Wystarczy że poszperasz w internecie a znajdziesz przyklady.
Teraz poczekam, czy znajdziesz jakies przykłady. Staraj się szukać także po angielsku.
Napiszę tylko że zamiast pętli możesz użyć find.
Chyba nie miałeś czasu szukać,
Przykłady:
$ grep -i "main" *
Plik binarny a pasuje do wzorca
a.c:int main(int argc, char **argv) {
a.c: gtk_main();
grep: nowy katalog: Jest katalogiem
ron:int main() { cout << "hello"; system("pause"); return 0; }
Na zielono masz pliki i katalogi, tak działa grep, w przyjaznej formie, a reszta to zawartość pliku
więcej znajdziesz w poleceniach ( wykonanych w terminalu )
I jak się pobawisz opcjami grep to osiągniesz to co pewnie chciałbyś,
czyli tylko pliki , tylko pliki tekstowe, z pominięciem katalogów i tylko zawierające słowo "main"
$ grep -lId skip "main" *
a.c
ron
W twojej pętli wyglądałoby to tak
#!/bin/bash
for i in `ls -la | grep ^"-" | awk '{printf $9 " " }'`
do
grep -lI "main" $i && echo " znalazlem plik"
done
Czyli grep sprawdza plik i jeśli wynik będzie pozytywny zostanie wykonana komenda " echo " znalazlem plik" "
A oto wynik skryptu
$ ./test
a.c
znalazlem plik
ron
znalazlem plik
test
znalazlem plik
Działa idealnie ?
Moim zdaniem działa, tylko po co pisac skrypt jak można uzyć samej komendy grep z opcjami jak wyżej ;D
( a plik test, to owy skrypt który uruchamiałem )
A teraz przykład z find , oco mi chodziło ?
$ find . -type f | xargs grep -lI "main"
./ron
./test
./a.c
find wyszuka w ". " bierzącym katalogu , typ pliki " f " i nastepnie komenda grep "-l " wyswietla tylko nazwy plików , " -I " bez plików binarnych i ze słowem "main"
Oczywiście jak wyżej już wspomniałem można użyć samo grep , z możliwością podania scieżki do kataloguoraz czy rekurencyjnie w podkatalogach czy nie,
a pętle for możemy stworzyć gdy potrzebujemy wykonać bardziej skomplikowane operacje na pliku.
Edytowane:
$ find . -type f | xargs grep -lI "main" | awk '{ print $1, "\n znalazłem plik" }'
./ron
znalazłem plik
./test
znalazłem plik
./a.c
znalazłem plik
$ grep -lId skip "main" * | awk '{ print $1, "\n znalazłem plik" }'
a.c
znalazłem plik
ron
znalazłem plik
test
znalazłem plik