Jak wykryć nowe pliki w folderze ze skryptem bash ? Chciałbym przetworzyć pliki, jak tylko zostaną utworzone w folderze. Czy to możliwe, czy muszę zaplanować skrypt z cronem, który co minutę sprawdza nowe pliki?
Jak wykryć nowe pliki w folderze ze skryptem bash ? Chciałbym przetworzyć pliki, jak tylko zostaną utworzone w folderze. Czy to możliwe, czy muszę zaplanować skrypt z cronem, który co minutę sprawdza nowe pliki?
Odpowiedzi:
Powinieneś rozważyć użycie inotifywait
jako przykładu:
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
W Ubuntu inotifywait
zapewnia inotify-tools
pakiet. Od wersji 3.13 (bieżącej w Ubuntu 12.04) inotifywait
będzie zawierać nazwę pliku bez opcji -f. Starsze wersje mogą wymagać przymusu. Należy zauważyć, że -e
opcja inotifywait
jest najlepszym sposobem filtrowania zdarzeń. Ponadto twoje read
polecenie może przypisać dane wyjściowe pozycji do wielu zmiennych, które możesz użyć lub zignorować. Nie ma potrzeby używania grep / sed / awk do wstępnego przetwarzania danych wyjściowych.
inotifywait
Było tylko to, co chciałem.
The '--filename' option no longer exists. The option it enabled in earlier versions of inotifywait is now turned on by default.
Więc musisz tylko zrobić, inotifywait -m /path -e create |
ja spróbuję edytować tę odpowiedź.
fswatch
. Nie napisałem tego, ale jest to oprogramowanie typu open source i korzystam z niego.
Wolę incron
, ponieważ jest łatwiejszy w zarządzaniu. Zasadniczo jest to usługa, która wykorzystuje inotify
i możesz konfigurować konfiguracje, aby podejmować działania w oparciu o operacje zmiany plików.
Dawny:
<directory> <file change mask> <command or action> options
/var/www/html IN_CREATE /root/scripts/backup.sh
Pełny przykład możesz zobaczyć tutaj: http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/
Właśnie to ugotowałem i nie widzę z tym żadnych większych problemów, poza niewielką szansą na brakujące pliki między czekami.
while true
do
touch ./lastwatch
sleep 10
find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done
Jeśli przetwarzanie pliku nie trwa zbyt długo, nie możesz przegapić żadnego nowego pliku. Możesz także przedstawić działania w tle ... Nie jest to kuloodporne, ale służy pewnym celom bez zewnętrznych narzędzi, takich jak inotify.
inotify
nie jest dostępne. Dodałbym, -type f
aby odfiltrować tylko pliki. W przeciwnym razie folder również zostanie zwrócony.
-f filename
opcja jest świetna. Pozostaje więc tylko pytanie, jak to zrobić, aby ponownie uruchomić komputer. Zamierzam użyć tego z moją elektrownią słoneczną, aby os.system("ssh me@mysystem ' ( touch /home/me/alarms/low24 ) '")
następnie utworzenie tego pliku spowodowało, że komputer główny użyje espeak
i ogłosi niskie napięcie. Już wysyła mi wiadomość e-mail, ale ponieważ mój system już mówi godzinę w szczycie, ma całą resztę. askubuntu.com/questions/977613/…
Możesz użyć watch
w swoim skrypcie
watch -n 0.1 ls <your_folder>
Monitoruje folder i wyświetla wszystko w nim co 0,1 sekundy
Wada
To nie jest czas rzeczywisty, więc jeśli plik został utworzony i usunięty w mniej niż 0,1 sekundy, to nie działałoby, watch
obsługuje tylko 0,1 sekundy.
Zakładam, że folder docelowy (nazywam to isempty
dla wygody) jest pusty i czekasz na upuszczenie jednego lub więcej plików.
Możesz użyć następującego polecenia:
ls -1A isempty | wc -l
po prostu, aby sprawdzić, czy folder jest nadal pusty, w rzeczywistości zwróci 0, jeśli nie ma nowego pliku (stąd isempty
folder jest nadal pusty) lub, z drugiej strony, zwróci wartość większą niż 0 (w rzeczywistości liczba plików aktualnie znajdujących się w folderze).
To powiedziawszy głupi test „jeśli / to” może zrobić resztę pracy:
if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
Oczywiście do_something
funkcja będzie musiała manipulować plikami w isempty
folderze, a następnie usunąć go (same) z samego folderu po przetworzeniu.
Dodanie do tabeli crontab wiersza takiego jak poniższy uruchomi sprawdzanie raz na minutę i uruchomi do_something
akcję, jeśli folder nie jest oczywiście pusty:
* * * * * if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
ls
skryptów. find
Zamiast tego użyj prostego globowania: mywiki.wooledge.org/ParsingLs
Jeśli chcesz wykryć nowe pliki, przetwórz je, a na koniec usuń kontynuowane pliki, możesz użyć systemd.path . Ta metoda opiera się na inotify. Istnieje opcja DirectoryNotEmpty, więc systemd może uruchomić skrypt zawsze, gdy wykryje jakieś pliki w katalogu. Musisz pamiętać, że to zadziała tylko wtedy, gdy będziesz mógł usunąć pliki i skrypt pozostawi katalog pusty.
Najpierw przygotuj plik mymonitor.service
[Unit]
Description=Start the script
[Service]
Type=oneshot
ExecStart=/path/to/your/script
następnie przejdź do mymonitor.path, aby zdefiniować ścieżkę
[Unit]
Description= Triggers the service
[Path]
DirectoryNotEmpty=/path/to/monitor
[Install]
WantedBy=multi-user.target
Jeśli nazwa pliku .path jest taka sama jak nazwa usługi, nie ma potrzeby określania nazwy usługi w pliku .path.
Opiera się na monitorowaniu dostępu do plików dla manekinów
entr
Używanie entr
to nowy sposób na zrobienie tego (jest to platforma wieloplatformowa). Uwaga entr
nie używa odpytywania, co daje ogromną przewagę nad wieloma alternatywami.
Wykorzystuje
kqueue(2)
lub,inotify(7)
aby uniknąć odpytywania.entr
został napisany, aby szybkie sprzężenie zwrotne i automatyczne testy były naturalne i całkowicie zwyczajne.
Na BSD używa pledge(2)
Możesz go zainstalować za pomocą
apt-get install entr
dnf install entr
Możesz śledzić katalog nowych dodatków za pomocą
while $(true); do
# echo ./my_watch_dir | entr -dnr echo "Running trigger..."
echo ./my_watch_dir | entr -dnr ##MY COMMAND##
done;
Opcje wyjaśnione (z dokumentów),
-d
Śledź katalogi zwykłych plików podanych jako dane wejściowe i zakończ, jeśli zostanie dodany nowy plik. Ta opcja umożliwia także jawne określenie katalogów. Pliki o nazwach rozpoczynających się od „.” są ignorowane.-n
Uruchom w trybie nieinteraktywnym. W tym trybie entr nie próbuje czytać z TTY ani zmieniać jego właściwości.-r
Załaduj ponownie trwały proces potomny. Podobnie jak w przypadku standardowego trybu działania, narzędzie, które kończy działanie, nie jest uruchamiane ponownie, dopóki nie zostanie przetworzone zdarzenie systemu plików lub klawiatury.SIGTERM
służy do zakończenia działania narzędzia przed jego ponownym uruchomieniem. Utworzono grupę procesów, aby uniemożliwić skryptom powłoki maskowanie sygnałów.entr
czeka na zamknięcie narzędzia, aby upewnić się, że zasoby takie jak gniazda zostały zamknięte. Kontrola nad TTY nie jest przenoszona na proces potomny.
Bash nie może tego łatwo zrobić. Musisz w zasadzie uzyskać listę wszystkich plików w folderze i okresowo uzyskać nową listę i porównać je, aby zobaczyć, co się zmieniło.
To, czego szukasz, nazywa się inotify. Jest wbudowany w jądro Linuksa i możesz w zasadzie siedzieć i czekać, aż coś się wydarzy, w którym wraca funkcja inotify i mówi „hej, jest nowy plik o nazwie foobar”
Aby osiągnąć to, co chcesz, musisz przełączyć się na coś takiego jak Perl i użyć Linux :: Inotify2 (python prawdopodobnie również obsługuje inotify, ale jestem osobą perla).
Działa to w cygwin i Linux. Niektóre z poprzednich rozwiązań, które zapisują plik, spowodują uszkodzenie dysku. Ten scipt nie ma tego problemu:
SIG=1
SIG0=$SIG
while [ $SIG != 0 ] ; do
while [ $SIG = $SIG0 ] ; do
SIG=`ls -1 | md5sum | cut -c1-32`
sleep 10
done
SIG0=$SIG
ls -lrt | tail -n 1
done
Poniżej znajduje się skrócona wersja przykładu przepływu stosu , który przetestowałem i włączyłem do jednego z moich projektów, który wymaga monitorowania określonych katalogów.
Var_dir="${1:-/tmp}"
Var_diff_sleep="${2:-120}"
Var_diff_opts="--suppress-common-lines"
Func_parse_diff(){
_added="$(grep -E '>' <<<"${@}")"
if [ "${#_added}" != "0" ]; then
mapfile -t _added_list <<<"${_added//> /}"
_let _index=0
until [ "${#_added_list[@]}" = "${_index}" ]; do
_path_to_check="${Var_dir}/${_added_list[${_index}]}"
if [ -f "${_path_to_check}" ]; then
echo "# File: ${_path_to_check}"
elif [ -d "${_path_to_check}" ]; then
echo "# Directory: ${_path_to_check}"
if [ -p "${_path_to_check}" ]; then
echo "# Pipe: ${_path_to_check}"
fi
let _index++
done
unset _index
fi
}
Func_watch_bulk_dir(){
_current_listing=""
while [ -d "${Var_dir}" ]; do
_new_listing="$(ls "${Var_dir}")"
_diff_listing="$(diff ${Var_dec_diff_opts} <(${Var_echo} "${_current_listing}") <(${Var_echo} "${_new_listing}"))"
if [ "${_diff_listing}" != "0" ]; then
Func_parse_diff "${_diff_listing}"
fi
_current_listing="${_new_listing}"
sleep ${Var_diff_sleep}
done
}
Oto link do skryptu, który używa zmodyfikowanej wersji powyższej do automatycznego odszyfrowywania plików lub katalogów znajdujących się w punkcie montowania sshfs; wyżej wspomniany projekt.