[Megoldva] fájltörlés scriptből

Fájltörlést szeretnék végrahajtani scriptből, de nem egyszerű számomra a művelet.
Ugyanis nem a létrehozási dátum a mérvadó, hanem ami fájlnévben szerepel.

Pld. Blabla_AT_2010-nov-25_10-25.ext

A Blabla változhat, az ext meg a kiterjesztés, és az is változhat.
Leszeretném törölni szkript segítségével az aktuális dátumnál 1 nappal régebbi DÁTUM NEVŰ fájlokat, függetlenül attól hogy azok mikor keletkeztek.
Emiatt nem jöhet szóba az mtime
find ${dir}/ -name "*AT*.sh" -mtime +1 -exec echo rm -f {} \; -print
Milyen ötletek vannak?

Hozzászólások

man date

Valami ilyen kell neked:
date -d yesterday +"%Y-%b-%d"

Ilyesmi lesz:
find . -name "*AT_`date -d yesterday +"%Y-%b-%d"`*.sh"

(Valóban végig kell keresni az alkönyvtárakat is?)

1) Lekerdezed a mai datumot, a honapot 3-betus formaban ahogy a fileban van.
2) Megkeresed az osszes filet ami megfelel a mai napnak
3) Leirtod a tobbit.

Ez feltetelezi, hogy nincsenek jovobe mutato fileok.

Igy ilyesmi jonne ki: find ${dir}/ -not -name "*AT*_$(date +"%Y")-$(date +"%b" | tr '[:upper:]' '[:lower:]')-$(date +%d)_*" -exec echo rm -f {} \; -print

Sajnos ez nem jó. Lehet értetlen voltam. A cron, vagy az at számára készül egy szkript amely felveszi NÉVként azt a dátumot amikor el kell indulnia. Pld. két napja létrehoztam hogy februárban hajtódjon végre.
Ekkor ez lesz a fájl neve: blabla_AT_2011-febr-02_10-25.ext

Ma van a törlés. Nos mivel ezt a fájlt két napja hoztam létre, az általad írt parancs simán kitörli.
Holott erre még szükség van mert februárban el kell indulnia. Ezért is van benne a NEVÉBEN hogy 2011-febr.
Remélem most már érthető.
Tehát NÉV alapján kell letörölni, és nem az elkészítés dátuma alapján.
Nos ez a problémám.

Az en megoldasom sem az elkeszites datuma alapjan torol, hanem a filenevben szereplo datum alapjan. Viszont abban igazad van, hogy a megoldasom feltetelezte, hogy jovobeni file nincs, pedig megis.

Ezesetben azt lehet tenni, hogy fogod a fileokat, felparsolod, kiszeded a datumot, sortolod, levagod a megtartani kivantakat, aztan a tobbit lehet torolni.

Pl van blabla_AT_2011-feb-02-10_25.ext, blabla_AT-2009-maj-01-11_23.ext

Kiszeded a datumot: 2011-feb-02, 2009-maj-01. Itt van egy kis szivas, mert a feb, maj stb-t at kene alakitani szamra, de azt is meg lehet oldani. Atalakitod pl 20110202 formara, maris egyszeruen sortolhato. Megkeresed a datumot ami elottieket torolni kell, es azt, meg a felette levoket levagod. Aztan visszaalakitod 2011-feb-02 formara, es maris lehet globolni es torolni.

Mondjuk egyszerubb lenne, ha a filenevben eleve valami ertelmes, parsolhato modon lenne benne a datum.

A dátum kinézete megoldható. De nekem ezek a szövegek még kínaiak. sort az okés. Rendezem. De mi az hogy felparsolom?
Meg globolni? Eddig egy valamire való 400 valahány soros szkriptem van a sok kicsi mellett. De ez még korántsem jelenti azt hogy tudnék programozni. Ha tudnék nem kérdeznék.. :)
Csináltam egy ilyent, de ezek szerint ezzel még nem sokra megyek:
find ${dir}/ -name "*AT*.sh" | awk -vFS='T_' '{print $2}' | awk -vFS='_' '{print $1}'
Ekkor megkapom csak a dátumokat:
2010-10-30
2010-11-25
2011-02-01

A date parancs kellemes jószág, tud sok szép és okos dolgot. Például azt, hogy a megadott időpontig hány másodperc telt el 1970-01-01 00:00:00 UTC óta. Ezt elosztva 86400-zal megkapod napokban:


zeller@demo:~$ date
2010. nov. 25., csütörtök, 19.45.55 CET
zeller@demo:~$ echo $(($(date +%s)/86400))
14938
zeller@demo:~$ echo $(($(date -d yesterday +%s)/86400))
14937
zeller@demo:~$ 

Én a fájlnévbe így (vagy így is) berámolnám a dátumot, aztán a törlésnél ezt nézném, hogy kisebb-e, mint a megadott (és ilyen formára hozott) érték.

Vagy egy marha egyszerű megoldás: szétszórod a dátumnak megfelelő könyvtárakba (amiket ha nincsenek, szépen létrehozol a fájl elkészítése előtt):

ide/év/hónap/nap/foo-év-hónap-nap-bar.ext

Aztán lehet is rm -rf törölgetni a már fölösleges könyvtárakat.

perl.
ez kell neked.

tegyük fel, hogy megoldod, hogy xxx2011-02-23yyy alakuak legyenek a fajlnevek.


find 'dir' -name 'glob' -type f | perl -e 'while (<>) { chomp; next unless =~ ^/^xxx(\d+)-(\d+)-(\d+)yyy$/o; next unless mktime(0,0,0,$3,$2-1,$1-1900) < time()-86400; unlink $_; }'

na valami ilyesmi kb. azt csinalja, amit szeretnel.


#!/bin/bash
set -e -u -C

cd /path/to/files/

# store list of files in a shell variable
# NO SPACES, NO TABS, NO NEWLINES, NO BACKSLASHES, ETC
FLIST=$(ls -1)

# format the upper limit on deletion as number of seconds since the Epoch
LIMIT=$(date -d 'now - 1 day' +%s)

# get a list of timestamps in "month day year hour:minute" format from FLIST
# convert them to seconds since the epoch
# paste them with the original list of files
# select files below the limit
# remove selected files
sed -r 's/^.*([0-9]{4})-([a-zA-Z]{3})-([0-9]{2})_([0-9]{2})-([0-9]{2}).*$/\2 \3 \1 \4:\5/' <<<"$FLIST" \
| date -f - +%s \
| paste - <(printf '%s\n' "$FLIST") \
| while read STAMP FNAME; do
    if [ "$STAMP" -lt "$LIMIT" ]; then
      # printf is also a bash builtin
      printf '%s\n' "$FNAME"
    fi
  done \
| xargs rm --

Húúú!
Még egyszer húúú.
Ezt még a sed ákombákom kivételével érteném is, de nem működik.
Tehát adott egy főmappa, melybe létrehozásra kerülnek almappák, de ezeknek nincs közük a dátumokhoz. Ezen almappákba 3 különböző kiterjesztésű fájl kerülhet.
Ebből ami érdekes az csak az sh végződésű, de abból kettőféle is keletkezhet. Egy a CRON számára, illetve az AT számára. Ami a CRON számára készül azokat nem kéne piszkálnom, csak az AT-t tartalmazókat. Ezért szűrtem meg én az AT-re.
Az AT-t tartalmazó fájlnév így néz ki:
blabla_AT_2010-11-20_20-08.sh Vagyis hogy mikor kell végrehajtódnia. Ha végrehajtódott, szeretnék tőlük megszabadulni.
De nem a krusaderrel, mc-vel, hanem szeretném ezt szkriptből vezérelni.
S nekem a főmappát kell szkennelnem, mert az azon belüli almappákban bárhol lehetnek AT fájlok eldobálva.
A főmappában nincsenek fájlok.
Ennek ismeretében ha lenne valaki olyan jó srác hogy ezt a sed-es megoldást kijavítaná, azt megköszönném.
Nekem a sed nagyon kínai még.


--- a/prune.sh  2010-11-25 23:21:23.000000000 +0100
+++ b/prune.sh  2010-11-25 23:22:12.000000000 +0100
@@ -5,17 +5,17 @@
 
 # store list of files in a shell variable
 # NO SPACES, NO TABS, NO NEWLINES, NO BACKSLASHES, ETC
-FLIST=$(ls -1)
+FLIST=$(ls -1 */*_AT_????-??-??_??-??.sh)
 
 # format the upper limit on deletion as number of seconds since the Epoch
 LIMIT=$(date -d 'now - 1 day' +%s)
 
-# get a list of timestamps in "month day year hour:minute" format from FLIST
+# get a list of timestamps in "year-month-day hour:minute" format from FLIST
 # convert them to seconds since the epoch
 # paste them with the original list of files
 # select files below the limit
 # remove selected files
-sed -r 's/^.*([0-9]{4})-([a-zA-Z]{3})-([0-9]{2})_([0-9]{2})-([0-9]{2}).*$/\2 \3 \1 \4:\5/' <<<"$FLIST" \
+sed -r -n 's/^.*_AT_([0-9]{4}-[0-9]{2}-[0-9]{2})_([0-9]{2})-([0-9]{2})\.sh$/\1 \2:\3/p' <<<"$FLIST" \
 | date -f - +%s \
 | paste - <(printf '%s\n' "$FLIST") \
 | while read STAMP FNAME; do
@@ -24,4 +24,4 @@
       printf '%s\n' "$FNAME"
     fi
   done \
-| xargs rm --
+| xargs -r rm --

Megoldási szkeleton, élesben nem használandó ilyen formában:

find / -name '*.akarmi' -exec ./nevellenorzo.sh "$(date)" {} \; -a -exec echo rm {} \;

A ./nevellenorzo.sh meg várjon két paramétert, dobd össze ügyesen, hordozhatóan, és pontosan akkor adjon vissza igaz (0) errorlevel értéket, ha törölhető a fájl! Nó varrantj! Ne puncolj, dolgozz meg a pénzedért bazz!

1. A dátumot csak egyszer értékeljük ki, hátha éjféltájt fut.
2. A "-a" néhány find implementációban elhagyható, néhányban tilos, néhányban kötelező! Szopófaktor, próbálkozni kell, illetve $(man find) a _cél_gépen!
3. Azért nem "find LÓFASZ ... -print0 | xargs -0 rm" csővezeték van, mert ha néhány núbiai még nem találkozott _egy könyvtáron_ belül 600000+ darab oracle log reguláris fájllal, amit szűrőn nem fogsz tudni átpasszírozni!!! Ilyenkor szoktunk pl. aix, hp-ux alatt find-dal köcsögölni sokat. Lassabb lesz, de stabilabb a dedikált törlés egyenként.

Munkát, kenyeret, illetve az egyiket!

http://www.youtube.com/watch?v=QXz7-BNC6jw
http://nocirc.org/

Nos miután ez nekem nem jött össze, addig agyaltam míg rá nem jöttem a legkézenfekvőbb megoldásra.
Annyira egyszerű mint a faék.
Ugye nekem az volt a gondom hogy leszeretném törölni az végrehajtódott AT scripteket.


######## data into at #########
at_data="$(mktemp -p /tmp)" # hozz létre ideiglenes fájlt
printf "cd ${dir} \n" > ${at_data} # ugorj a megfelelő mappába
printf "./${name}_AT_$(date +%Y)-${HH}-${NN}_${OO}-${PP}.sh \n" >> ${at_data} # hajtsd végre a parancsot
printf "rm -f ${name}_AT_$(date +%Y)-${HH}-${NN}_${OO}-${PP}.sh \n" >> ${at_data} # Ha lefutott, akkor töröld a scriptet.
/usr/bin/at -mf ${at_data} ${OO}:${PP} ${HH}/${NN}/$(date +%Y) 2>/dev/null # adat az at időzítőbe
rm -f ${at_data} # töröld az ideiglenes fájlt.
######## end data ###########

S hála Istennek, ez akkor is működik, ha a script utolsó sorában a
printf "#/usr/bin/sudo /sbin/shutdown -h now \n" parancs van.