Hur man utför en uppgift när en ny fil läggs till i en katalog i Linux

Denna handledning visar dig hur du använder Linux-filsystemhändelser (notify) för att få meddelanden varje gång en fil dyker upp i en katalog. Du kan använda dessa som utlösare för att automatisera vanliga uppgifter på ditt system.

Vi kommer att skriva ett skript som övervakar en katalog och agerar på nya filer som läggs till. Varje fil är gzippad och flyttas till en annan katalog, så snart den upptäcks. Skriptet använder undersystemet inotify, genom ett verktyg som kallas inotify-tools. Men först, låt oss installera verktyget och experimentera.

Installerar inotify-tools och gzip

Använd apt-get för att installera det här paketet på ditt system om du använder Ubuntu eller en annan Debian-baserad distribution. På andra Linux-distributioner, använd din Linux-distributions pakethanteringsverktyg istället.

sudo apt-get install inotify-tools gzip

Experimenterar med inotify-verktyg

Låt oss börja med att titta på en katalog och se vilka händelser som startar när nya filer kommer in. Vi kommer att använda ett verktyg som heter inotifywatch , som är en del av inotify-tools. Skapa en ny katalog som heter ”inkommande”:

mkdir incoming

Börja titta på den här katalogen genom att utföra följande kommando:

inotifywatch -v incoming

Detta kommer att instruera inotify att titta efter alla filsystemhändelser i katalogen ”inkommande”. Alternativet -v gör att verktyget skriver ut extra information om vad det gör. Vi har inte angett ett timeoutalternativ (-t ), och kommandot kommer att fortsätta samla in händelser tills vi avslutar med CTRL+C. Vid det här laget bör vår terminal se ut ungefär så här:

Öppna ett nytt terminalfönster (eller flik) och byt till inkommande katalog. Använd pekkommandot för att skapa en ny fil med namnet ”newfile”.

cd incoming/
touch newfile

Gå nu tillbaka till det första terminalfönstret och stoppa inotifywatch genom att trycka på CTRL+C.

En tabell med händelser kommer att serveras till konsolen, som indikerar en instans av ”skapa”, ”öppna”, ”attrib” och ”stäng_skriv.” Dessa fyra händelser inträffade när vi använde touch för att skapa en ny fil, ställde in dess filåtkomstattribut, öppnade den för att skriva ett noll-avslutande tecken och stängde den sedan. Dessa är bara några av de många händelser som kan övervakas på ett filsystem med inotify-verktyg. Du kan se hela listan på huvudsidan för inotifywatch.

För våra ändamål är vi bara intresserade av två evenemang:

”skapa” – när en fil skapas i målkatalogen.
”moved_to” – när en fil flyttas från en annan plats till målkatalogen.

Låt oss försöka inotifywatch igen, men den här gången instruerar vi den att endast övervaka dessa två händelser. Kör detta kommando i det första terminalfönstret:

inotifywatch -v -e create -e moved_to incoming

I det andra terminalfönstret eller fliken, låt oss försöka skapa en ny fil, ändra dess innehåll och sedan flytta filen från en annan plats till målkatalogen. Alla dessa kommandon körs från hemkatalogen.

touch incoming/created
echo Testing123 >> incoming/created
touch /tmp/created2
mv /tmp/created2 incoming/

Gå tillbaka till det första terminalfönstret och stoppa inotifywatch genom att trycka på CTRL+C. Vi kommer att se följande utdata:

Endast två händelser räknades: skapa en fil som heter ”created.txt” och flytta en befintlig fil som heter ”created2.txt”. Allt annat, som att ändra ”created.txt”, ignorerades.

Titta på en katalog och utföra en uppgift

Nu när vi vet vilka händelser vi ska följa kan vi använda ett annat verktyg som heter inotifywait för att blockera exekvering tills en fil skapas i eller flyttas till vår målkatalog. Vi kommer att använda samma argument som vi gjorde med inotifywatch och även specificera hur vi vill att filnamnet ska formateras för användning i vår uppgift.

Innan vi börjar behöver vi en katalog för filer som redan har bearbetats. Skapa en katalog som heter ”bearbetad”:

mkdir processed

Skapa sedan ett nytt skript som heter ”watch-incoming.sh” och lägg till innehållet nedan:

#!/bin/bash

TARGET=~/incoming/
PROCESSED=~/processed/

inotifywait -m -e create -e moved_to --format "%f" $TARGET 
        | while read FILENAME
                do
                        echo Detected $FILENAME, moving and zipping
                        mv "$TARGET/$FILENAME" "$PROCESSED/$FILENAME"
                        gzip "$PROCESSED/$FILENAME"
                done

Skriptet kör kommandot inotifywait med alternativet -m. Detta gör att kommandomonitorn ändras på obestämd tid. Varje gång en ny händelse upptäcks skickas filnamnet till läskommandot och injiceras i variabeln ”FILENAME”. Blocket under while-loopen exekveras, där filen först flyttas till den ”bearbetade” katalogen och sedan gzippas. Originalfilen ersätts med den komprimerade filen och filnamnet kommer att sluta med ”.gz”.

Låt oss ge körrättigheter för det här skriptet och köra det från vår hemkatalog.

chmod u+x watch-incoming.sh
./watch-incoming.sh

Öppna det andra terminalfönstret och skapa en ny fil i katalogen ”inkommande”. Lista innehållet i både ”inkommande” och ”behandlade” katalogen för att se resultaten av händelsen som upptäcks:

Den råa textfilen som vi kopierade till katalogen ”inkommande” upptäcktes av skriptet, kopierades till ”bearbetad” och komprimerades sedan med gzip.

Vi kan göra några intressanta uppgifter nu när vi kan se efter nya filer som kommer till en katalog. Till exempel kan vi lägga till en vattenstämpel till bildfiler, komprimera råvideor till mp4-format och till och med ladda upp varje ny fil vi ser till en Amazon S3-hink. Det här skriptet är en bra utgångspunkt för att rulla dina egna arbetsflöden och automatisera vanliga uppgifter på ditt system.