Räkna antal rader i en fil och dela upp den i 2 filer med Bash script

Trädvy Permalänk
Medlem
Registrerad
Aug 2017

Räkna antal rader i en fil och dela upp den i 2 filer med Bash script

Jag har ett Bash script som jag kör en gång i timmen som bla läser lite information från en enhet via mitt nätverk via SNMP-get och sparar denna information i en textfil.
Jag vill nu dela upp min textfil automatiskt när den börjar bli för stor (tex då antalet rader är över 1000).

Utdrag ut mitt script
Filen <test.sh>:
= = = = =
# Lägg till datum i tillfällig fil
date > /Users/admin/Documents/script/temp

# Lägg till publik IP i slutet på tillfällig fil
curl ifconfig.me >> /Users/admin/Documents/script/temp

#Lägg ny data i början på loggfilen
cat /Users/admin/Documents/script/temp /Users/admin/Documents/script/logg.txt > temp2 && mv temp2 /Users/admin/Documents/script/logg.txt

# Rensa bort temp
rm /Users/admin/Documents/script/temp

= = = = =
(Kan ha blivit några stavfel.. och det går kanske att slå ihop filerna utan att skapa en tillfällig fil...)

Nu till mitt problem.

Jag vill dela upp min loggfil i en ny fil när den börjat bli för stor.
Tex:
Om antalet rader är mer än 1000
Flytta rad 500-1000 till en ny fil: Logg(Datum).txt
Ta bort rad 500-100 från logg.txt

Det jag får problem med är när jag ska räkna raderna i filen.
Jag har provat: wc -l < /Users/admin/Documents/script/logg.txt | xargs
Detta ger mig antalet rader när jag kör kommandot från terminalen. Men jag lyckas inte skapa en If sats som använder resultatet från "wc -l" kommandot i mitt script.
Jag vill omvandla resultatet, som jag misstänker är en String, till en Integer så att jag kan köra:

IF( 1000 < (wc -l < /Users/admin/Documents/script/logg.txt | xargs))
THEN
xxxx
ELSE
FI

Tar gärna emot tips på hur detta fungerar eller andra alternativ som kanske är bättre lämpade.

Trädvy Permalänk
Forumledare
Registrerad
Okt 2002

Titta förslagsvis på standardverktyget split:

SPLIT(1) Commands NAME split - split a file into pieces SYNOPSIS split [OPTION]... [FILE [PREFIX]] DESCRIPTION Output pieces of FILE to PREFIXaa, PREFIXab, ...; default size is 1000 lines, and default PREFIX is 'x'.

Annars är AWK en gammal arbetshäst när det gäller liknande filhantering, men det är en icke-trivial best att sätta sig in i.

Vad gäller datatyper så är skalskript generellt inte typade, så att omvandla en sträng till ett heltal är inte relevant (däremot så använder test-kommandot olika operatorer beroende på om du vill jämföra strängar eller tal).

Din if-syntax är inte giltig så som den är skriven: du får titta på test-kommandot och "command substitution". Vad xargs har i dina exempel att göra är oklart — det blir nog bättre av att helt skippa det .

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Okt 2007

Tja,

En variant utan dina första grejer med IP och datum, men själva uppdelandet kan skrivas på följande sätt.

##############
#!/bin/bash
log=log.txt

#Kollar om antalet rader i $log är större än 1000
if [[ "$(cat $log|wc -l)" -gt 1000 ]]
then
echo run
#Skrver alla rader förutom sista 500 till ny log
head -n -500 "$log" >> log_"$(date +%F)".txt
#Skriver sista 500 raderna till aktuell temporär logfil
tail -n 500 "$log" > "$log".temp
#Flyttar temporär logfil till aktuell
mv "$log".temp "$log"
else
echo nope
fi
##############

Trädvy Permalänk
Medlem
Registrerad
Sep 2013

Lite märkligt angreppssätt, jag hade använt ett verktyg avsett för jobbet, nämligen logrotate.

Om du kan leva med att rotera på ett tidsintervall istället för antal rader i filen, skapa en logrotate-konfigurationsfil för din loggfil, ex: /etc/logrotate.d/logg:

/Users/admin/Documents/script/logg.txt { daily rotate 7 missingok notifempty }

That's it.

Med ovanstående konfiguration kommer logrotate rotera din loggfil till logg.1, logg.2, ... logg.7 och sedan ta bort den äldsta filen. Du kan ange hur ofta loggfilerna skall roteras och hur många som skall sparas (med mera):

man logrotate

fyi: logrotate invokeras via cron (se /etc/cron.daily/logrotate)