it-swarm-eu.dev

Skript pro sledování složky pro nové soubory?

Jak zjistit nové soubory ve složce pomocí skriptu bash ? Chtěl bych zpracovat soubory, jakmile jsou vytvořeny ve složce. Je to možné, nebo musím naplánovat skript s cron , který kontroluje nové soubory každou minutu?

141
ihatetoregister

Jako příklad byste měli zvážit použití inotifywait:

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

V Ubuntu poskytuje inotifywait balíček inotify-tools. Od verze 3.13 (aktuální v Ubuntu 12.04) bude inotifywait obsahovat název souboru bez volby -f. Je možné, že bude třeba vynutit starší verze. Důležité je poznamenat, že volba -e Pro inotifywait je nejlepším způsobem filtrování událostí. Příkaz read může také přiřadit poziční výstup do více proměnných, které můžete použít nebo ignorovat. K předběžnému zpracování výstupu není třeba používat grep/sed/awk.

168
enzotib

Jen jsem to uvařil a neviděl jsem s tím žádné velké problémy, kromě malé šance na chybějící soubory mezi kontrolami.

while true
do
       touch  ./lastwatch
       sleep 10
       find /YOUR/WATCH/PATH -cnewer ./lastwatch -exec SOMECOMMAND {} \;
done

Pokud zpracování souboru netrvá příliš dlouho, neměli byste si ujít žádný nový soubor. Mohli byste také pozadí aktivity ... Není to důkaz důkaz, ale slouží k některým účelům bez externích nástrojů, jako je inotify.

28
Michael Sacchi

Dávám přednost incron , protože jeho snazší správa. V podstatě jde o službu, která využívá inotify a můžete nastavit konfigurace tak, aby prováděly akce na základě operací se změnami souborů.

Příklad:

<directory> <file change mask> <command or action>  options
/var/www/html IN_CREATE /root/scripts/backup.sh

Celý příklad můžete vidět zde: http://www.cyberciti.biz/faq/linux-inotify-examples-to-replicate-directories/

27
rynop

Ve skriptu můžete použít watch

watch -n 0.1 ls <your_folder>

Sleduje vaši složku a uvádí v ní vše v ní každých 0,1 sekundy

Nevýhoda

Není reálný čas, takže pokud byl soubor vytvořen a odstraněn za méně než 0,1 sekundy, pak by to nefungovalo, watch podporuje pouze minimum 0,1 sekundy.

26
GypsyCosmonaut

Předpokládám, že cílová složka (pro větší přehlednost ji nazývám isempty) je prázdná a čekáte, až tam bude vynechán jeden nebo více souborů.

Můžete použít následující příkaz:

ls -1A isempty | wc -l

stačí zkontrolovat, zda je složka stále prázdná, ve skutečnosti vrátí 0, pokud neexistuje žádný nový soubor (složka isempty je tedy stále prázdná), nebo naopak vrátí hodnotu větší než 0 (ve skutečnosti počet souborů aktuálně ve složce).

To znamená, že hloupé, jestli/pak test dokáže zbytek práce:

if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi

Funkce do_something Bude samozřejmě muset manipulovat se soubory ve složce isempty a po zpracování je odstranit (odstranit) ze samotné složky.

Pokud do crontab přidáte řádek, jako je následující, spustí se kontrola jednou za minutu a pokud není složka samozřejmě prázdná, spustí akci do_something:

* * * * *     if [ $(ls -1A isempty | wc -l) -gt 0 ] ; then do_something ; fi
9
ztank1013

entr

Používání entr je nový způsob, jak toho dosáhnout (je to multiplatformní). Poznámka entr nevyužívá dotazování, což je obrovská výhoda oproti mnoha alternativám.

Používá kqueue(2) nebo inotify(7), aby se zabránilo dotazování. entr byl napsán tak, aby rychlá zpětná vazba a automatizované testování byly přirozené a zcela běžné.

Na BSD používá pledge(2)

Můžete jej nainstalovat pomocí

apt-get install entr
dnf install entr
brew install entr

Můžete sledovat adresář pro nové doplňky pomocí

while $(true); do
  # echo ./my_watch_dir | entr -dnr echo "Running trigger..."
  echo ./my_watch_dir | entr -dnr ##MY COMMAND##
done;

Možnosti vysvětleny (z dokumentů),

  • -d Sledujte adresáře běžných souborů poskytovaných jako vstup a výstup, pokud je přidán nový soubor. Tato volba také umožňuje explicitní zadání adresářů. Soubory se jmény začínající na „.“ Jsou ignorovány.
  • -n Spustit v neinteraktivním režimu. V tomto režimu se entr nepokouší číst z TTY ani měnit jeho vlastnosti.
  • -r Znovu načtěte trvalý podřízený proces. Stejně jako u standardního provozního režimu není obslužný program, který se ukončí, znovu spuštěn, dokud nebude zpracována událost systému souborů nebo klávesnice. SIGTERM se používá k ukončení obslužného programu před jeho restartem. Je vytvořena skupina procesů, která zabraňuje skriptům Shell maskovat signály. entr čeká na ukončení obslužného programu, aby zajistil uzavření zdrojů, jako jsou sokety. Řízení TTY se nepřenáší podřízeným procesem.
8
Evan Carroll

Pokud chcete detekovat nové soubory, pak je zpracovejte a na konci smažte pokračující soubory, které můžete použít systemd.path . Tato metoda vychází z inotify. Existuje možnost DirectoryNotEmpty, takže systémd může skript spouštět vždy, když detekuje všechny soubory v adresáři. Musíte si pamatovat, že to bude fungovat pouze v případě, že můžete smazat pokračované soubory a skript ponechá adresář prázdný.

Nejprve připravte soubor mymonitor.service

[Unit]
Description=Start the script

[Service]
Type=oneshot
ExecStart=/path/to/your/script

dále přejděte na mymonitor.path a definujte cestu

[Unit]
Description= Triggers the service

[Path]
DirectoryNotEmpty=/path/to/monitor

[Install]
WantedBy=multi-user.target

Pokud je název souboru .path stejný jako název služby, není třeba v souboru .path specifikovat název služby.

Vychází z Monitorování přístupu k souborům pro figuríny

7
Dawid Wolski

Bash to nemůže udělat snadno. Museli byste v podstatě získat seznam všech souborů ve složce a pravidelně získat nový seznam a porovnat je, abyste viděli, co se změnilo.

To, co hledáte, se nazývá inotify. Je zabudován do linuxového jádra a můžete tam v podstatě sedět a čekat, až se něco stane, kdy se vrátí inotify a řekne: „Hej, existuje nový soubor s názvem foobar“

Chcete-li dosáhnout toho, co chcete, musíte přejít na něco jako Perl a používat Linux :: Inotify2 (python pravděpodobně také podporuje inotify, ale já jsem Perl osoba).

2
Patrick

Funguje to v cygwin a Linux. Některá z předchozích řešení, která zapisují soubor, způsobí, že se disk rozbije. Tento scipt nemá tento problém:

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
0
user1186515

Níže je zkrácená verze příkladu stackoverflow , kterou jsem testoval a začlenil do jednoho z mých projektů, který vyžaduje monitorování konkrétních adresářů.

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
}

Zde je odkaz na skript , který používá upravenou verzi výše k automatickému dešifrování souborů nebo adresářů nalezených v jeho bodu připojení sshfs; výše uvedený projekt.

0
S0AndS0