Jak używać inotifywait do oglądania katalogu do tworzenia plików o określonym rozszerzeniu


21

Widziałem tę odpowiedź .

Jako przykład należy rozważyć użycie inotifywait:

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        # do something with the file
    done

Moje pytanie brzmi: powyższy skrypt obserwuje katalog do tworzenia plików dowolnego typu, ale jak zmodyfikować inotifywaitpolecenie, aby raportowało tylko wtedy, gdy plik określonego typu / rozszerzenia zostanie utworzony (lub przeniesiony do katalogu) - np. Powinien zgłoś, kiedy .xmlutworzony zostanie dowolny plik.

CO SPRÓBOWAŁEM:

Uruchomiłem inotifywait --helppolecenie i przeczytałem opcje wiersza polecenia. Ma --exclude <pattern>i --excludei <pattern>poleceń WYKLUCZAJă pliki niektórych typów (przy użyciu regex), ale muszę sposób obejmować tylko pliki określonego typu / rozszerzenia.


BTW, użycie pathpowyższego prawdopodobnie nie jest najlepszą nazwą zmiennej, jeśli chcesz grać z tym pierwszym w powłoce. Jeśli go użyjesz, nie będziesz w stanie używać poleceń i wszystkiego, ponieważ to po prostu przesłoniło standard PATH. Dlatego zalecam użycie alternatywnej nazwy var, takiej jak fpathzamiast. tj. while read fpath action filewtedy każde standardowe polecenie zwykle dostępne z twojej powłoki nadal będzie.
Baptiste Mathus

to trochę śmieszne, że nie ma opcji włączania.
erandros

Odpowiedzi:


17

jak zmodyfikować polecenie inotifywait, aby raportować tylko po utworzeniu pliku określonego typu / rozszerzenia

Pamiętaj, że jest to kod niesprawdzony, ponieważ nie mam inotifyteraz dostępu do niego . Ale coś podobnego powinno działać:

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        if [[ "$file" =~ .*xml$ ]]; then # Does the file end with .xml?
            echo "xml file" # If so, do your thing here!
        fi
    done

2
To działa i przetestowałem to z inotifywait.
TheBetterJORT

1
Jak to robisz? Czy to polecenie jednorazowe, czy musi działać w pętli lub coś w tym rodzaju? Być może w ramach incron(mam nadzieję, że nie).
SDsolar,

@SDsolar To się zmienia. Dla mnie zwykle uruchamiam inotifyalbo z nohupniestandardową usługą systemową. Najczęściej ten drugi.
maulinglawns

9

Użyj podwójnego ujemnego:

inotifywait -m --exclude "[^j][^s]$" /path -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
    done

Dotyczy to tylko plików javascript


1
Fajnie, podoba mi się to, że przesuwa filtrowanie, inotifywaitzamiast generowania ogromnych wyników dla wszystkich plików, a następnie filtruje (jak w drugiej odpowiedzi). Nie próbowałem, ale myślę, że działałoby to trochę szybciej.
TMG

Właśnie tego szukałem. Jak zmodyfikować dane --excludewejściowe, aby szukać .extplików. Jest to uruchamiane tylko raz lub w pętli for?
kurokirasama

To demon, więc będzie działał, dopóki się nie zawiesi lub go nie
wyłączysz

Przepraszamy, brakowało pierwszego pytania. inotifywait -m --exclude "[^.][^e][^x][^t]$" /home/jonas/Skrivbord/test -e create -e moved_to | while read path action file; do echo "The file '$file' appeared in directory '$path' via '$action'" done Jestem pewien, że wyrażenie regularne można zoptymalizować, ale to dziecko działa :)
Jonas Earendel,

Dzięki! Wypróbuję to!!
kurokirasama,

3

Chociaż podejście podwójnie negatywne z poprzedniej odpowiedzi jest dobrym pomysłem, ponieważ (jak zauważył TMG) ​​rzeczywiście zmienia ono zadanie filtrowania inotifywait, nie jest poprawne.

Na przykład, jeśli plik się kończy, asto nie będzie pasował, [^j][^s]$ponieważ ostatnia litera snie pasuje [^s], dlatego nie zostanie wykluczony.

W języku boolowskim, jeśli Sjest to zdanie:

„ostatnia litera to s

i Jjest stwierdzeniem:

„przedostatnia litera to j

wówczas wartość --excludeparametru powinna być semantycznie równa not(J and S), co według praw De Morgana jest not(J) or not(S).

Innym potencjalnym problemem jest to, że zsh, $pathjest wbudowany w zmiennej reprezentującej odpowiednik tablicy $PATH, więc while read path ...linia będzie całkowicie bałagan $PATHi wszystko by stać się przyczyną unexecutable z powłoki.

Dlatego prawidłowe podejście to:

inotifywait -m --exclude "[^j].$|[^s]$" /path -e create -e moved_to |
    while read dir action file; do
        echo "The file '$file' appeared in directory '$dir' via '$action'"
    done

Zwróć uwagę na .to, co jest potrzebne po, [^j]aby upewnić się, że dopasowanie zostanie zastosowane w przedostatniej pozycji, a także, że |znak (reprezentujący wartość logiczną OR wspomnianą powyżej) nie powinien być tutaj zastępowany, ponieważ --excludeprzyjmuje rozszerzone wyrażenia regularne POSIX.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.