Shell scriptek [megoldva]

Hello, megint én... :)

Szóval elkezdtem csinálni konkrét (iskolai) feladatokat shell scriptinggel, de pár feladattal elakadtam, és a gugli sem és a manual sem segített igazán.

Első ami ilyen, hogy kell egy számsort kiírni 1-től 100-ig, amiben csak a párosak szerepelnek. Nos addig eljutottam, hogy az összes számot hogyan kéne:
"for (( i=1; i<=100; i++ )); do echo $i; done". Ez tök jól kidobálja a terminálba a számokat, de arra sehogy sem jöttem rá, hogy a számtani sorozat differenciáját hogyan kéne beiktatni.

Aztán van egy olyan feladat, hogy meg kell adni, hogy mely paranccsal található meg a /usr-ben a "legmélyebb" könyvtár. Majd az utolsó olyan, hogy a /usr-ben lévő összes fájl kumulatív eloszlását kell kell elkészíteni és azt ábrázolni GNUPlottal log-log skálán, majd egy ponton hatványfüggvényt kell illeszteni.

Az a baj, hogy sehol sem találok hozzá megfelelő segítséget és jó lenne, ha meg tudnám oldani ezeket órán is.

Aki segít, annak örök hálám!

Üdv,
Tomato

UPDATE: A feladatokat megoldottnak tekintem. Köszönöm szépen mindenkinek a sok segítséget, tanácsokat, tippeket-trükköket! Sokat tanultam ma!

Hozzászólások

Ez nem lenne jó?


for ((i=2; i<100; i+=2 )); do echo $i; done

Amúgy hol, mit tanulsz?

A $x leirasatol nekem borsodzik a hatam. A ${x} a helyes irasmod. Nagyon ritkan, ha olyan a script eredetileg es csak keves modositast csinalok benne, en is leirok egy $VALAMI-t, de akkor se szeretem.
--


()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

A második feladatra rávezetés (a teljes megoldás rád vár, de ha nem megy, kérdezz nyugodtan):

man find:
"-printf format
  %d File’s depth in the directory tree; 0 means the file is a command line argument.
  %p File’s name.

-type c
  d directory"

Használható hozzá a sort parancs numerikus rendezéssel, és a head (vagy tail) az egy sor kivágásához.

egy favágó megoldás könyvtármélységre:
find /usr/ -type d| sed -e 's,[^/],,g'| sort | tail -1 | wc -c

ebből kettőt le kell vonni, mert a /usr elején a / a 0. szint és mert van egy newline karakter is a végén.

utána a

find /usr -mindepth $melyseg -type d

megmondja, hogy mely könyvtárak ezek

ez:
find /usr -type f| sed -e 's,\(.*\)/\([^/]*$\),\1,'| sort | uniq -c | sort -n

meg elég favágó módon csinál egy listát, hogy melyik könyvtárban hány fájl van.

Az utolsó feladatnál a fájlok méretének eloszlását kell ábrázolni?

A fenti find -printf alapú megoldás kis módosítással erre is jó, aztán a kapott listát rendezd numerikusan és mentsd el egy fájlba. Ez triviális.

Ami nem triviális, az a hatványfüggvény illesztése.

A gnuplot illesztő algoritmusa kényes sok mindenre, többek között arra is, ha a paraméterek nagyságrendje között nagy eltérés van.
Úgy célszerű megadni a függvényt, hogy f(x) = (x/a)**b.

Az illesztésnél pedig ajánlott kijelölni azt a tartományt, ahol tényleg teljesül a hatványfüggvényszerű viselkedés. Ehhez kénytelen vagy ábrázolni az eloszlást, megnézni, hogy a log-log skálán nagyjából hol egyenes-szerű a görbe, és azt a tartományt a megadni a fitnek, pl így:

fit [25000:220000] f(x) 'usrsizes.txt' u 0:1 via a,b

Nálam b = 2.67 :)
Az ábrázolásnál pedig vedd az yrange-t mondjuk [0.5:*]-ra, hogy a logaritmikus skála ne ugasson a 0 méretű fájlok miatt.

Köszönöm szépen az eddigi segítségeket.

Ilyet is sikerült összehalásznom:
find . -printf '%d\n' | sort -n | tail -1

Azzal a gnuplotossal az a baj, hogy az első részét nem igazán értem. vagyis hogy mit kéne kezdeni pontosan. :( Esetleg tudsz bővebben segíteni?

Köszi Mindenkinek!
-Tomato

Mármint minek az első részét nem érted, és mivel akarsz mit kezdeni? :)

Először is: a fájlok méretének az eloszlását kell ábrázolni?
A fenti parancssorod ehhez majdnem jó, csak %d helyett %s és a végén tail helyett irányítsd át a kimenetet egy fájlba.
(Tipp: ne find .-ot használj az /usr-ből, hanem find /usr-t és dolgozz a home könyvtáradban.)

Utána gnuplot, és help logscale, help plot, help plot using.

Ha abszolút semmit nem tudsz a gnuplotról, akkor olvasgass róla, hidd el, később nagyon hasznos lesz.
Kezdetnek egy tömör (és sajnos elavult) magyar leírás: http://rail.ttk.pte.hu/kmatyas/meresiadatcd/dokumentacio/gnuplot_magyar…

Igen, erre gondoltam. Utána célszerű együtt plottolni az adatokat és az illesztett függvényt, hogy tényleg illeszkedik-e.

A gnuplot parancsokat pedig be lehet írni egy fájlba, lehet címet és tengelyfeliratot adni az ábrának és el lehet menteni eps-be, és akkor lesz igazán szép a megoldás.

Nézd meg, hogy a log-skálázott x tengelyen a [60000:70000] intervallum hova esik, és mekkora helyet foglal el.
Nekem az ábra alapján úgy tűnik, hogy arra a tartományra illik a függvény.
Ha ez a tartomány volt megadva a feladatban, akkor készen vagy. Ha nem, és neked kell megválasztani a tartományt, akkor jobban jársz a [4000:20000] vagy [20000:60000] tartományokkal, vagy e kettő uniójával.

"Nonlinear fitting is an art", ahogy bölcs emberek mondták. Itt az történik, hogy neked van egy primitív modelled (egy sima hatványfüggvény) az adatok leírására, de ez a modell túl egyszerű, nem adja vissza azok minden tulajdonságát.
Ránézésre látszik, hogy van két tartománya az eloszlásnak, amikre a hatványfüggvényes modell egész jó, de két különböző kitevővel. Az egész adatsorra viszont egyáltalán nem jó a modell.

Ha ez egy valós fizikai probléma lenne, akkor új, bonyolultabb modellt kellene keresned. Például egy olyat, ami két különböző kitevőjű hatványfüggvényből áll egy küszöbértékkel, ami elválasztja a kettőt. Ha ez érdekel, akkor nézd meg a gnuplot.info-n a demok között az illesztéseket: ott van példa ilyen tört függvény illesztésére.

find /usr -type d | awk -F\/ '{print NF, $0}' -ból ki lehetne indulni...


most=0
for i in $(find /usr/ -type d -print | awk -F\/ '{printf "%d_%s\n", NF, $0 }' | sort -nr )
do
set $(echo $i | sed 's/_/\ /')                                 
if [ $1 -ge $most ]
then
 echo $2
 most=$1
fi
done

Ezzel az összes olyan könyvtárat kiírod, aminek maximális a mélysége.

jessszus:)

először is az awk az, amit utoljára használnék hordozhatóra tervezett programban, mert az még linuxok között sem egyforma. A debianban is van mawk, nawk meg gawk, ezek közül a gawk a legótvarosabb.
egy echo-t meg egy sed-et forkolni minden sorra egy olyan embertől, aki szerint a find drága művelet, hát nem is tudom:)
ha már ilyen barbár módon csinálod, akkor
while read p1 p2
és úgy állapítom meg hogy nagyobb-e a most-nál.

de mivel az awk-kal már úgyis halálra bonyolítottad, ezért érdemesebb az awk-ban megcsinálni, hogy ami kisebb, azt ki se írja.

ja, ha dash sh-ra van linkelve, akkor köteles sh-ként működni, ha nem, akkor bugreport

Ha nagyon szép megoldást szeretnénk, akkor az IFS-t /-re cserélve, read-del tömbbe beolvastatva a könyvtárneveket, a tömb méretére van bash beépített függvény, az megmondja, milyen mély a könyvtárstruktúra. A konkrét megoldást az olvasóra bízzuk:)

Igazad van!

TEMPFILE=/tmp/enyime_es_tuti_hogy_egyedi_de_ha_megtalalod_torold_le_nyugodtan_$$
if [ -e $TEMPFILE ]
then
TEMPFILE=/tmp/basszus_az_elozo_letezett_$$_de_ez_tuti_nem_$$
fi

trap "rm $TEMPFILE" SIGINT SIGTERM

find /usr/ -type d -print > $TEMPFILE
MOST=`awk -F/ '{if ( most < NF ) { most = NF }} END {print most}' $TEMPFILE`
awk -v most="$MOST" -F/ '{if ( most == NF ) { print $0 }}' $TEMPFILE

rm $TEMPFILE

Ezeket csakazert nem raktam bele, mert marcsaka csicsazas, a feladat mar az a 4 sor megoldotta.
A tempfilet csak shell tombbel lehetne helyettesiteni, hogy jo is legyen, de annyit szerintem most nem er.

Szerintem ezzel meg is oldottam a problemat: