bash script kérdés

Fórumok

Sziasztok,

A segítségeteket szeretném kérni:-)

bash scripttel meg lehet azt oldani, hogy minden első és második napot kékkel írjon a naptár, és minden ötödik és hatodik napot pedig pirossal?
Annyit kitaláltam, hogy a cal program lenne a barátom ehhez, de nem tudom, hogy hogyan kellene felparaméterezni.

for i in `cal`

do
echo $i
done

És itt az én tudásom sajnos meg is áll, szépen kilistázza 31 ig, mivel, hogy most augusztus van.

Meg kellene határoznom a kezdő napot, az utolsó napot, hogy tetszőlegesen mozoghassak a naptárban, és valahogy meg kellene mondanom a scriptnek, hogy az első és a második nap az piros, utána jön két nap, amihez ne nyúljon, majd jön megint 2 nap, ami pedig legyen kék színű.

Ez túl bonyolult a bash nek? Ehhez már python vagy c programot írnának a guruk?
Próbálkoztam a googlin keresni cal awk kulcsszavakkal, de nem találtam ilyen típusú scriptet, amiből kiindulhattam volna.

Szerintem az awk biztos tudja ezt, de az én awk tudásom az addig tart, hogy meg tudom változtatni az elválasztó karaktert, és ez alapjén tetszőleges mezőt nyomtatni, próbálkoztam az awk mélyebb megértésével, de sajnos még nem találtam olyan leírást, amiből igazán megérteném az awk erejét -gondolom- amikor az awk külső programfájlból dolgozik.

Tudna valaki egy kicsit segíteni?

Üdv,

Zoli

Hozzászólások

bashish


echo -e "$(cal -h |\
  sed -ne '/^\ *[0-9]/s/\(......\)\(......\)\(......\)\(...\)/\\e[34m\1\\e[39m\2\\e[31m\3\\e[39m\4/p')"

cal -h?

cal -h

Usage:
 cal [options] [[[day] month] year]

Options:
 -1, --one        show only current month (default)
 -3, --three      show previous, current and next month
 -s, --sunday     Sunday as first day of week
 -m, --monday     Monday as first day of week
 -j, --julian     output Julian dates
 -y, --year       show whole current year
 -V, --version    display version information and exit
 -h, --help       display this help text and exit

cal -V
cal from util-linux 2.23.2

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

bashish perlish



cal -h | perl -p az_alabbi_script.pl


#!/usr/bin/env perl
sub c {
	$m = $_[0] % 7;
	my $c;
	if($m==1||$m==2) {
		$c="34";
	}
	elsif($m==5||$m==6) {
		$c="31";
	}
	return $c;
}

s/[\x5f\x08]//g; # ez azért kell hogy a mai napot kiemelõ verzérlõkarakterek ne osszák szét a dátumszámot, de cal -h kapcsolóval nem érdekes

s/\d+/"\x1b[".c($&)."m".$&."\x1b[m"/ge;

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

de, mũködik. sõt egy szám módosításával 8 napos ciklussal számol, amint azt kiderítettük.
neked mit dob vissza, ami nem jó?

itt van egy parancs sorban az egész:


cal -h | perl -pe 'sub c {
        $m = $_[0] % 8;
        my $c;
        if($m==1||$m==2) {
                $c="34";
        }
        elsif($m==5||$m==6) {
                $c="31";
        }
        return $c;
}
s/\d+/"\x1b[".c($&)."m".$&."\x1b[m"/ge;
'

elsõ sorban "% 8" a ciklusok hossza, $c a szín ascii escape sekvenciájának a változó része, a "cal" kimeneti sorainak az átalakítását a s/.../.../ge utasítás végzi.

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

minden első és második napot kékkel írjon a naptár, és minden ötödik és hatodik napot pedig pirossal

nem egyértelmũ, 7-napos ciklusok napjairól van szó?

~~~~~~~~
Linux 3.2.0-0.bpo.4-486
Debian 6.0.7

nem akarok hetes ciklust, ne nézze a heteket, csak azt, hogy 2 nap kék, 2 nap semmi, 2 nap piros stb.

(annyi a story, hogy a barátnőm 2 napot nappalos, 2 napot éjszakás, közte 2 nap szünettel, tekintet nélkül a hétvégére, és színezte a jövő évi naptárat és ekkor jutott eszembe, hogy ez egy jó téma lenne bash scriptet gyakorolni) Úgy ültem le 1,5 órán át googlozni, hogy na majd megoldom, de nem tudtam sajnos. Az a baj, hogy nem tudom a határokat, mármint, hogy meddig lehet még valamit megoldani bash scripttel és mikor kell már egy másik programozási nyelv. Mivel én kezdő vagyok bash ből, és még kezdőbb c nyelvből nem tudom megállapítani az ilyen feladat nehézségét.

-- Zoli

nem hordozható bash:


today=$(date +%Y%m%d)
start=${1:-$today}
# pattern="bb..rr.."
pattern="bb..rr"

main()
{
i=0
while true
do
  case ${pattern:$((i%${#pattern})):1} in
    b) col='\x1b[31m'
       ;;
    r) col='\x1b[34m'
       ;;
    .|*) col='\x1b[39m'
       ;;
  esac
  echo -e $col$(date -d "$1 + $i days" +%Y.%m.%d.)
  i=$((i+1))
done
}

trap "echo -e '\x1b[39m'; exit 0" SIGINT SIGTERM SIGHUP
main $start

Hasonlóan néz ki a kimenete, mint a 'cal -ym' -nek:


#!/usr/bin/python
from calendar import day_abbr, month_name, monthrange
from datetime import date, datetime, timedelta


start=date(2013,8,18)
cycle='bb..rr'
year=datetime.today().year


def colorize(d,n,t):
    col=colors[cycle[(d-1+n)%len(cycle)]]
    if t: col+=colors['reverse']
    return col+("%2d"%d)+neutral
    

colors={ '.': '\x1b[0m', 'b': '\x1b[34;1m', 'r': '\x1b[31;1m', 'reverse': '\x1b[7m' }
neutral=colors['.']
offset=(date(year,1,1)-start).days
dnames=' '.join([d[:2] for d in day_abbr])
today=datetime.today().date()

M=[]
for month in range(1,13):
    first,days=monthrange(year, month)
    pad=['  ']*(42-days)
    mname=month_name[month].center(20)
    D=pad[:first]+[colorize(d,offset,date(year,month,d)==today) for d in range(1,days+1)]+pad[first:]
    L=[mname,dnames]+[' '.join(D[i*7:i*7+7]) for i in range(6)]
    M.append(L)
    offset+=days

print str(year).center(66)
print ''
for i in range(4):
    R=M[i*3:i*3+3]
    for line in range(8):
        print '   '.join([R[j][line] for j in range(3)])

#!/bin/awk -f

BEGIN {
    pattern="bb..rr";
    FPAT="^.{2}|.{3}";
    l=length(pattern);
}

/^ *[^[:digit:] ]/ {
    print;
    next;
}

{
    for (i=1; i<=NF; i++) {
        if ($i ~ /^ +$/) {
            printf ($i);
            continue;
        }
        if (p>l || p<1) p=1;
        switch (substr(pattern, p, 1)) {
            case "r":
                color="\x1b[31;1m";
                break;
            case "g":
                color="\x1b[32;1m";
                break;
            case "b":
                color="\x1b[34;1m";
                break;
            default:
                color="";
        }
        p++;
        printf ("%s%s\x1b[0m", color, $i);
    }
    printf ("\n");
}

A cal-t kell belecsövezni:

cal -m | ./dt p=3

A p értéke megmondja, hogy a pattern hanyadik elemétől induljon a hónap első napja.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Pontosan erre gondoltam!!

Nagyon köszönöm! Tökéletes. Csak kár, hogy én nem tudnám magamtól megirni, de elemzem a kódodat, hátha tanulok belőle.

Valami apró hiba lehet benne, ha azt írom be, hogy:

cal 2014 | ./dt p=3

Akkor november 20 21 22 fele-fele színeződik meg, mármint az első kettes kék, az utolsó kettes pedig piros színű. Elvágja a színezés a számokat. Ugyanez augusztusnál és még egy pár helyen.

-- Zoli

Igen, mert nem készítettem fel arra az esetre, ha a cal-lal egyszerre több hónapot nyomtatsz. Ez csak addig működik jól, amíg egy hónap van nyomtatva. Olyannyira, hogy több hónap esetén soronként megy végig a színezésen, így a különböző hónapok egy-egy sorait színezve eleve hibás napok lesznek megjelölve. Szóval ez csak egy-egy hónapra alkalmas, erre figyelj!

Úgy látom, időközben kiderült, hogy nem 6, hanem 8 napos ciklusaid vannak, így javítsd ki a pattern változó értékadását:

pattern="bb..rr.."

Szerk.: a p=3 csak példa, p értékével tudod eltolni, melyik nappal kezdje a színezést.

Szerk. 2: a pattern változóban használhatsz g betűt is, azok a napok zöldek lesznek.

Szerk. 3: A számokat azért vágja el rossz helyen, mert fix mezőszélességeket használok - lásd az FPAT értékadását -, így amikor bekerül egy másik hónap az első mellé, szétcsúszik az egész.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

ok, akkor így fogom használni.

Te hogyan tanultad meg az awk -t ilyen jól?

Nézegettem a szabilinux ot, a linuxvilág cikkeket, meg megvettem a Pere László héjprogramozás c. könyvét, olvasgattam, próbálgattam ezekból az anyagokból, de sajnos nem tudtam megtanulni az awk-t ennyire jól.

-- Zoli

Ha arra van szükséged, hogy egyszerre több hónapot is láss, akkor szerintem jobban jársz, ha magát a cal parancsot írod meg awk-ban - vagy bármilyen más nyelven - úgy, hogy igény szerint színezzen. Annak nyilvántartása, hogy a cal kimenetén soron belül mely számok mely hónaphoz tartoznak, s így színezni lényegesen bonyolultabb, mint generálni egy naptárat rögtön színesen.

A bonyolultságról: az első sorban a következő hónap aktuális részét úgy tudnád színezni, hogy az első hónap napjainak számából kiszámolnád, a pattern mely részével kellene kezdeni a következő hónap első sorban lévő napjainak színezését. Ehhez tudni kell, hány napos a hónap, modulot számolgatni, effélék. Szóval lényegesen egyszerűbb egyből jó naptárat generálni, mint a cal kimenetét színezni több hónap ábrázolása esetén.

Én Büki András: UNIX/Linux héjprogramozás című könyve által kaptam kedvet a bash, awk, s efféle nyalánkságokhoz, de ennek már több, mint 10 éve.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Ha nem akarsz ezzel vacakolni, akkor csak a lényegre koncentrálj, azaz a napok megjelenítésére, színezésére. Magára a dátumra nem kell, mert az awk-ból - helyesebben a gawk-ból - lehet system() függvénnyel linuxos parancsot hívni, így lehetőséged van a date parancs hívásával kiszámoltatni, milyen nap az, amit ki szeretnél íratni. A date parancs formátuma szabadon meghatározható, például n=22; date -d @$[1376985300+n*86400] +%F, vagy valami ilyesmi.

Itt ugye kihasználtam, hogy egy nap 86400 másodperc, és egy bázis időponthoz képest toltam el 22 nappal az időt. A 22 nap csak példa, a módszert mutattam meg. A date parancs pedig visszaadja az évszám-hónap-napot. Nyilván a bázis időhöz való hozzáadást, a szorzást még awk-ban kellene végezni, s egyből a nyerő számot adni a date-nek, itt csak a módszert mutattam be.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A példám épp ezt tette. :) Ugyanakkor azért javasoltam az awk-ban számolást, mert most arról beszélünk, hogy egy awk scriptben hogyan oldható ez meg. Viszont most látom, túlbonyolítottam, nem kell külső parancsot hívni, mert van az awk-ban strftime() függvény.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

"Fel kell rakni a gawk-t, hogy működjön. (nem néztem meg, miben tér el a mawk-tól)"

Nem is akármilyet, ui. a switch-case szerkezet a gawk rengeteg nem sztandard szolgáltatása között is az egyik legújabb, és a nem is feltétlenül fordítja még bele minden disztribcsomagoló.

Lásd: man gawk
/GNU EXTENSIONS

"If gawk is configured with the --enable-switch option to the configure command, then it accepts an additional control-flow statement"

(Egyébként lassan megérne egy térképet az, hogy milyen feltételek mellett milyen fícsörök engedélyezettek és tiltottak, mert amilyen egyszerű maga a nyelv, ez annyira szig. mon. bonyolódik.)

Nem volt kritika implikálva, csak tétova érdeklődés jeleit látom itt, egyik kedvenc nyelvem környékén.

Egyébként mániám az asszociatív tömböket felhasználni a döntési rutinpk rövidítésére.



BEGIN {
   acolorfmt["r"] = "\x1b[31;1m%s\x1b[0m"
   acolorfmt["g"] = "\x1b[32;1m%s\x1b[0m"
   acolorfmt["b"] = "\x1b[34;1m%s\x1b[0m"
}

...
   colorid = substr(pattern, p, 1)
   colorfmt = ((colorid in acolorfmt) ? acolorfmt[colorid] : "%s")
   printf colorfmt, colorid
...

Sokadszor lepsz meg awk furmanyokkal, es ez itt megint ilyen, bar ovatosan azt mondanam, hogy nekem ugy remlik az (index in TOMB) tipusu konstrukcio mintha csak for ciklusban lenne szabvanyos. (Megneztem, opengroups.org szerint ez teljesen szabvanyos letezo kifejezes, akkor finomitok, mintha korai awk implementaciok nem szerettek volna mashol.) Akkor csak csettintek mar megint. (Kene valami debugger, amivel az ellenorizheto, hogy a 3 konnyen elerheto awk implementacioban melyik az, amelyik ezt a kodot futasdoben is gyorsabbak hajtja vegre, mint a millio if-et. De tudtommal ilyen a One-True-AWK-ban es a mawk-ban nincs, maradna a mindenre kiterjedo teszt.)

Nagyon szép, tetszik! Apró észrevétel, hogy nem színes r, g, b betűket kell kiírni, azaz a printf második argumentuma nem colorid. A colorid csak egy pattern egy karaktere, amelyik megmondja, az ugyanazon pozíciójú dátum milyen színű legyen.

Viszont a lényeg nagyon tetszik.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Sziasztok,

Tudnátok segíteni abban, hogy hogyan lehet egy usb-s 3G modemet újra felhúzni, ha eldobja a kapcsolatot?
Arra gondoltam, hogy betenném a parancsot egy script be és a monit programmal figyeltetném, de azt nem tudom, hogy honnan venné észre a monit, hogy elment a 3G kapcsolat. Gondoltam arra, hogy az nm-tool ból ki lehetne greppelni az aktuális állapotot vagy valami ilyesmi...

-- Zoli

Sziasztok!

Az alábbi script részletet szeretném beszúrni egy másik scriptembe, csak annyit szeretnék ellenőrizni, hogy a 3 program installálva van -e a rendszeren.
Ide föltettem a részletet:
http://pastebin.com/P9rrrRyW

De érdekes módon nem jól működik, a 3. if ágra nem működik, pedig nincsen fenn a disc-cover program, és mégsem lép bele ebbe az ágba. Tudnátok segíteni abban, hogy mi lehet a hiba? Az első kettő esetében működik.

Köszi,

-- Zoli

Azt hiszem, félreértettél. Ennél Replaced megoldása kulturáltabb.
Én arra gondoltam, hogy pl. vi-ból van millióféle. Létezik egy alap vi, amiben tán még a kurzorbillentyűk sem működnek, meg van mindenféle bővítése (nvi, vim, meg a bánat tudja még hány...), ha azt ellenőrzöd, hogy van-e vi, valószínűleg találni fogsz egyet, de kérdés, hogy az a sok közül melyik?
Ha arra vagy kíváncs, hogy pl. nvi telepítve van-e, akkor a csomagot célszerű lekérdezni, nem egy binárist, ami valószínűleg az adott csomag része.
Nem tudom érthetőbben elmondani.
(ráadásul, ha úgy van beállítva a shell, hogy hibánál megálljon - lásd: set -o errexit -, akkor nem is fut végig a szkripted)

Nem szeretném túl bonyolítani a dolgot. Sajnos nem is működik megfelelően a script, egy egyszerű ellenőrző mechanizmus részt szerettem volna az elejére beszúrni, hogy kicsit felhasználóbarátabb legyen a scriptem, amit nem is magamnak, hanem egy zenész barátomnak írtam, azzal a céllal, hogy egyszerűsítsem az életét a nagy mennyiségű cd archiváláshoz.
Ez a script: http://pastebin.com/rnxWD9iW
De hiába az előző beszúrásom, nem jól működik. Van valami bevett gyakorlat, hogy hogyan lehetne 3 program jelenlétét leelenőrizni a leghatékonyabban és kiírni, hogyha valamelyik a 3 közül hiányzik.

-- Zoli

Az a lényeg, ami szerintem nem esett le neked, hogy a parancs visszatér az exit kóddal, majd ennek $? értékét vizsgálod egy test segítségével, csak az a kérdés, minek. A test eredménye épp egy exit kód lesz, amelyre az if vagy végrehajtja, ami a then után van, vagy nem.

Akkor már nem egyszerűbb eleve az eredeti visszatérési értékkel megkínálni az if-et?

Mutatok példát arra, hogy vizsgáljuk, létezik-e egy alkönyvtár, s ha igen, akkor menjünk bele:

if [ -d "$directory" ]; then
  cd "$directory"
  valami parancs
  cd -
fi

Ugyanakkor ezt így is lehet, és szerintem szebb:

if cd "$directory" &>/dev/null; then
  valami parancs
  cd -
fi

A második esetben, ha az if-ben lévő cd sikeresen végrehajtódik, akkor a then utáni valami parancsot megcsinálja, de már bement a $directory-ba, hiszen éppen attól volt sikeres a cd.

Ha viszont nincs az illető alkönyvtár, akkor a cd hibakódot ad vissza, s így az if utáni then ág nem hajtódik végre, s az alkönyvtárba sem mentünk, mert az nem létezik, vagy nincs rá jogunk. A második megoldás ezért is jobb: az elsőben azt is vizsgálni kellene - amit most nem tettem meg -, hogy van-e jogosultságom arra, hogy az adott alkönyvtárba menjek.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az elsőnek az a baja, hogy a cd parancs fennakadhat még valamin, például jogokon. Az a biztos, amit megcsinált, akkor már tuti benn vagyunk a könyvtárban. Ha nem, akkor meg szinte mindegy is, miért nem: jogosultság, SELinux, hiányzó alkönyvtár, bármi.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

if ! cd "$directory" &>/dev/null; then
  mkdir -p "$directory"
  cd "$directory"
fi

Azért ezt akarhatom teljesen életszerűen. Bár tudom, így még egyszerűbb:

mkdir -p "$directory"
if ! cd "$directory" &>/dev/null; then
  echo "Jaj szegény fejemnek: '$directory'" 1>&2
  exit 1
fi

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

BUÉK mindenkinek!

Kipróbáltam, amit javasoltál. Ez nem jó sajnos arra, amire nekem kell.

Ha fenn van a flac, akkor működik, de ha nincs, akkor nem, és nekem az a lényeg, hogy akkor ugorjon az if ágra, ha nincs fenn a flac. De ezt írtam már.

if which "flac" >/dev/null; then echo flac is not installed; fi

Most így néz ki a scriptem: http://pastebin.com/1QbmJXR0

Jelen pillanatban azon gondolkozom, hogy kiegészítem egy cddb lekéréssel, csak még nem tudom, hogy hogyan. Nagyon nem szeretem a k3b-t, főleg ilyen ismétlődő feladatokra, mint a cd archiválás... - abban van cddb funkció.

Nem értek egy dolgot. Ha ezt írom be:

man flac 2>/dev/null

Akkor szépen elküldi a feketelyukba amit kiírna és újra promtot kapok.

De ha ezt írom be a fentihez hasonlóan, hogy:

man cdparanoia 2>/dev/null

Akkor nem küldi el a feketelyukba...

Valami köze lehet ahhoz, hogy jelen pillanatban nincs föltelepítve a flac, de a cdparanoia igen.
Ha leszedem a cdparanoia-t, akkor elküldi a feketelyukba a kimenetet, vagyis úgy működik, ahogy szeretném.
Azt nem értem, hogy miért függ ez a sor :

man cdparanoia 2>/dev/null

kimenete attól, hogy föl van -e telepítve a cdparanoia vagy sem.

A which es megoldásban azért nem mélyednék el, mert az 'depricated' -- nem én írtam, olvastam angol fórumokon.

Továbbra is keresek egy elegáns megoldást arra, hogy hogyan lehet egy ilyen kis egyszerű script elejébe beépíteni 3 if et úgy, hogy csak akkor ugorjon rá az ágra, hogyha az a program nincs fenn a rendszeren. mert ez a man-os megoldást, amit írtam az nem tetszik nekem. Lennie kell egy elegáns megoldásnak erre, csak még nem találtam meg.

-- Zoli

Már nincs kedvem magyarázni, próbáld megérteni:

#!/bin/bash

PROGS='cdparanoia flac disc-cover'
QUIT=0
for prog in $PROGS; do
    if ! type -p "$prog" &>/dev/null; then
        echo "Error: '$prog' is not installed!" 1>&2
        QUIT=1
    fi
done
[ $QUIT -eq 1 ] && exit 1

# Bla-bla...

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Tudom, sőt, lehet operálni azzal, hogy ha az első command exit code-ja 0, végrehajtódik a második, ennek exit code-jától függően a harmadik, de ha az első false végű, akkor rögtön a harmadik - nem - hajtódik végre.

Viszont ezek a megoldások sokat rontanak az olvashatóságon, szóval hacsak nincs rá valami különleges okom, nem élek az efféle vadításokkal. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Na jó, de ehhez már guru nak kell lenni:-) Sajnos nekem még nem mennek ezek a dolgok csípőből. Most "megvilágosodtam", mert van egy formulám arra, hogy hogyan lehet ellenőrizni mondjuk 3 program jelenlétét. én azt hittem, hoyg 3 if kell hozzá, vagy 1 if elágazás, de a feltételvizsgálatban vagy kapcsolatban lennének a programok. De ezzel a for ciklusos megoldással a legelegánsabb szerintem ez a megoldás. Fogalmam sem volt, hogy ehhez be kell vezetni egy quit változót is, de így, hogy megírtad helyettem már tudom.

-- Zoli

Nem kell bevezetni a QUIT változót, ki lehet lépni az if-ben is. Viszont azt szerettem volna, hogy amennyiben több szükséges program sincs feltelepítve, akkor kiírja az összes hiányzót, ezért lépek ki csak a végén.

Nem olyan szép, ha egyből kilépsz, mert akkor feltelepíted azt a programot, megint elindítod a scriptedet, most kiír egy másik hibaüzenetet, akkor feltelepíted azt, ez így kényelmetlen. Inkább sorolja fel az összes hiányzót egyszerre.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Pont így szerettem volna én is, hogy mindig csak azt sorolja fel, ami hiányzik és lépjen ki egy 1 es hibakóddal.

Abban még tudnál segíteni, hogya ezt szeretném 1 x az elején kiírni. ha hiányzik valamelyik program:
echo "The followings are missing:"

ha a for ciklusba teszem, akkor annyiszor írja ki, ahány program hiányzik, de az úgy nem az igazi:-)
Most ide tettem be: http://pastebin.com/DRSR8bFP

-- Zoli

Valljuk be, nem vagy könnyű eset. Mi lenne, ha gondolkodnál picit? Az azért jó, hogy nem adod fel, de ne légy már ennyire lusta!

#!/bin/bash

DEPENDS='cdparanoia flac disc-cover'
MISSING=''
for i in $DEPENDS; do
    if ! type -p "$i" &>/dev/null; then
        [ ! -z "$MISSING" ] && MISSING="${MISSING}, "
        MISSING="$MISSING$i"
    fi
done
if [ ! -z "$MISSING" ]; then
    echo "The followings are missing: $MISSING." 1>&2
    exit 1
fi

# Bla-bla

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Összefűztem, ha úgy tetszik, egymás után írtam két stringet. Próbáld ki:

a='alma'; b='fa'; echo "$a$b"

A konkrét példában az aposztrof illetve még az idézőjel is elhagyható, de ezt ne szokd meg, egyáltalán nem biztos, hogy egy stringben nincs szóköz, newline, vagy egyéb speciális karakter, mint például <, >, [, ], *, {, }, ;, &, meg fene tudja, hagy ne gondolkodjak.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Vagy inkább a -z a felesleges, hiszen a -e a fájl létezését ellenőrzi, a -z gyakorlatilag a nemlétezést. Ezért logikusabb a -z elhagyása :)

Egyébként én a felkiáltójel használatát igyekszem kerülni, és vagy egy && vagy egy || használatával ki is lehet váltani (persze az if-then-else is jó).

Sziasztok,

Tudnátok segíteni egy kicsit, az alábbit szerteném megoldani, de ez így nem jó, és nem tudom, hogy miért:

#!/bin/bash

echo "press [1] to start or [2] to stop the virtual FTP server"

answer=0
read answer

if [ $answer -eq 1 ]
then
vboxmanage startvm "FTP server" --type headless

if [ $answer -eq 2 ]
then
vboxmanage controlvm "FTP server" poweroff

else
echo "you can only use [1] or [2]"

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

Én így hallottam, éltem majd 3 évet amcsiban, így mászott a fülembe: you can only ... , de ez nem azt jelenti, hogy helyes is. Van egy jó könyvem, Usage and Abusage, Eric Partridge a szerző, ha megtalálom megnézem, hogy melyik a helyes Neked - meg persze magamnak is.

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

Az if-else nincs lezárva megfelelően, az $answer értéke pedig karakter lesz és nem szám így az összeahasonlítás is rossz. Erre az esetre inkább használj switch-et, illetve ha a read-el csak egy karaktert olvastatsz be, nem kell entert nyomni a leütött szám után. Valahogy így:


#!/bin/bash

echo "press [1] to start or [2] to stop the virtual FTP server"

answer=0
read -n 1 answer

case $answer in
"1")
vboxmanage startvm "FTP server" --type headless
;;
"2")
vboxmanage controlvm "FTP server" poweroff
;;
*)
echo "you can only use [1] or [2]"
;;
esac

update: a tabulátorokat valamiért sajnos letojja a code tag, de így is működik.

Mostanában túl sokat pythonkodtam, ott nem kell lezárni a blokkokat, nekem ezért nem tűnt fel.
Egyébként ha változókat hasonlítasz, akkor célszerű idézőjelbe tenni:
if [ "$valtozo" == "1" ]
then
...
fi

Ugyanis ha véletlenül szóköz is kerül a változóba, akkor szintaktikai hibát kapsz idézőjel nélkül.
(Persze ez csak a karakteres változókra vonatkozik)

Csak arra gondoltam (amit egyébként írtam is), hogy talán kezdjük azzal, milyen hibaüzenetet lát... :)
Nem tudom más hogy van vele, én a falnak tudok menni, mikor valaki úgy kérdez, hogy "Ez nem megy, de miért?" - miközben semmi hibaüzenetet nem említ, nem mondja, mit jelent nála a "nem megy", holott sok esetben (nem itt, de ez a ritkább) anélkül elég nehéz kitalálni.
Ezt meg némi barkóbázással kitalálhatta volna ő is (azt hiszem :) )

> "az $answer értéke pedig karakter lesz és nem szám így az összeahasonlítás is rossz"

No ez nem igaz. Ha semmi extra módon nem jelzed, akkor a (ba)sh-ban nincs szöveges/szám tipua a változónak, hanem pont a "szövegkörnyezet alapján használja a shell

a=1
b="1"
c='1'

A három értékadás között semmi különbség nincs.
A valódi probléma az if / else ágak illetve a lezárás hiánya volt.

Megtaláltam a könyvet, szerencsére.

Hoz egy rakás példát neves szerzőktől, és végül azt írja, hogy:

"...the natural place for only is usually next to the verb"

Lásd milyen rendes vagyok :-) (persze, hogy megteszek ennyit, hiszen Ti is mindig segítetek a linuxos kérdésekben - még így vasárnap is) :-)
Lefényképeztem az oldalt Neked:

http://kepfeltoltes.hu/view/140504/only_www.kepfeltoltes.hu_.jpg

Amúgy imádom az angolt, egy bizonyos szintig eljutottam, még a linuxot is azért szeretem, mert angol a dokumentáció nagy része:-)

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

Sziasztok,

Ezt az egyszerű dolgot szeretném megoldani, de állandóan valami hibádzik...

#!/bin/bash

current=0
max=65

current=$(df -h | grep uuid | awk '{print }' | awk -F % '{print $1}')

#while true
# do
if [[ "$current" -ge "$max" ]]
then
echo "more than 65%"
fi
# done

már próbáltam dupla [[ jelekkel, meg vagy 3 féle képpen... segítsetek légyszíves.-)

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

Juj... Első körben tegyük az egészet átláthatóbbá...


df -h | grep uuid | awk '{print }' | awk -F % '{print $1}'

helyett:


current=$(df -h | awk -F% ' /uuid/ {print $1 }')

Bár gondolom, neked inkább egy:


df -h | tr -d "%" | awk '/uuid/ { print $5 }'

kéne. Mindezt összerakva a vizsgálattal:


max=65
df -h | tr -d "%" | awk -v max=$max '/uuid/ && $5>= f { printf "%s usage %d more than %d%%\n", $1, $5, f }'

Inkább a -ge, nem?

Egyébként nem működik még mindig

Elkezdtem 100 mb os fájlokat gyártani a dd vel, és nem jezett a script, amikor átléptem a 65 öt, most éppen 67...

#!/bin/bash

max=65
current=0
current=`df -h | tr -d "%" | awk '/uuid/ { print $5 }'`

while true
do
if [ "$current" -ge "$max" ]
then
echo "higher than allowed"
sleep 5
fi
done

Szerintem azért, mert a while cikluson kívül veszi fel a current az éppen aktuális értéket, és amikor a ciklus ismétli önmagát, akkor nem vesz fel új értéket.

Átírtam így, most úgy tűnik, hogy jól működik:

#!/bin/bash

while true
do
if [ `df -h | tr -d "%" | awk '/uuid/ { print $5 }'` -ge 65 ]
then
echo "higher than allowed"
sleep 5
fi
done

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

Tekintve, hogy a current értéke lehet akár több sor is, így azt a shell ilyen formában nem jól tolerálja..

Próbáld meg inkább valami ilyen módon:

df -h| tr -d "%" | awk '/uuid/ { print $5,$6 }' |while read LINE
do
USAGE=$(echo $LINE|cut -f1 -d" ")
FS=$(echo $LINE|cut -f2 -d" ")
if [[ ${USAGE} -ge 65 ]]
then
echo "$FS utilization is higher than allowed (${USAGE}%)"
fi
done

____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Ezen mondjuk én is filóztam, mert ez nálam se megy. Max ennyire le tudom még egyszerűsíteni az egészet:
df -h |awk '/uuid/ {gsub ("%",""); if ($5 >= 95) print $6," FS utilization is higher than allowed:",$5,"%"}'
____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Ezzel óvatosan.. egyes df implementációk kiírják az inode kihasználtságot is, szóval az NF-1 ott pont nem ezt adja vissza, de a koncepció amúgy tényleg teljesen jónak tűnik :)
____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Kapcsolódva a témához: ki akartam segíteni a kérdezőt egy mini perl v. python szkripttel. A perl-nek az volt az akadálya, hogy egy külön telepítendő modult igényelt volna, olyat meg nem ajánlok, ha van egyéb megoldás is.
A python...

import posix
fs=posix.statvfs('/boot')
print (fs.f_blocks-fs.f_bavail)*100/fs.f_blocks

Ez ugye elvileg a felhasználható terület arányát írná ki?
Az a baj, hogy a df szerint 44%, a fenti 46%-ot hoz ki, ha a f_bavail helyett a f_bfree-t használom, akkor meg 41-et.
Miért ez az eltérés?
Rosszul számolok? (tőlem már az is kitelik)

Vagy rossz doksit nézel..

Itt pl egyértelműen leírja, hogy a NEM--super userek számára elérhető szabad blokkok száma.
https://docs.python.org/2/library/statvfs.html
F_BAVAIL - Free blocks available to non-super user.
____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Pedig az irány jó akkor, csak egy dolgot hagytál ki a számításból: a python alapból egészre kerekít mindent, és nem floating point-os számítást csinál. Mutatok egy példát:

#!/usr/bin/python
import posix
fs=posix.statvfs('/tmp')
print fs.f_blocks
print fs.f_bfree
print (fs.f_blocks-fs.f_bfree)*100)/fs.f_blocks

Ennek az eredménye nálam ez:
$ /tmp/python-test.py
8052573
591448
92.0

/* Amúgy ezek a számok 4k blockok ha jól értelmezem */

Ha ezeket az értékeket átlököm a bc-nek, akkor hasonló eredményt is kapok:
$ echo "((8052573-591546)*100)/8052573" |bc
92

Viszont ha megmondom bc-nek, hogy ne kerekítsen akkor más a helyzet:
$ echo "scale=4;((8052573-591546)*100)/8052573" |bc
92.6539

df szerint meg amúgy 93%-on áll ay FS (ergo df is csal csak az kerekít, nem az egészrészt veszi)

Tehát python-ban akkor a megoldás ez lenne:
#!/usr/bin/python
import posix
fs=posix.statvfs('/tmp')
print fs.f_blocks
print fs.f_bfree
print float((fs.f_blocks-fs.f_bfree)*100)/float(fs.f_blocks)

____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Kerekítési hibára gondoltam én is, de akkor csak eggyel térne el, itt meg nagyobb a különbség, ha jól számolok.
Lebegőpontosra konvertálva is az jön ki, hogy a df szerint 44% a használt, a pythonos számítások szerint meg vagy 41 (szabályosan lefelé kerekítve) vagy 46 (szintén szabályosan lefelé)

Az már csak mellékes, hogy az említett statvfs deprecated, csak nem tudom, mi van helyette :(

Akkor csináld már azt pls amit én, hogy megnézed, hogy a df pontosan mennyi blokkot mutat, illetve a statvfs meg mit lát (kalkuláld be hogy a block size eltérő lehet a df és a statvfs esetén) és aztán vesd össze a kettőt, és manuálisan végezd el a visszaellenőrző számításokat.
____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Azt csináltam. A python és a df azonos számokat mutat, kivéve a %Use oszlopot, amit pythonból számolnom kellett, annak ott van fent az eredménye.


~ $: df /boot
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 240972 98931 129600 44% /boot
~ $: python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> f=os.statvfs('/boot')
>>> f
posix.statvfs_result(f_bsize=1024, f_frsize=1024, f_blocks=240972, f_bfree=142041, f_bavail=129600, f_files=62248, f_ffree=61936, f_favail=61936, f_flag=4096, f_namemax=255)
>>> x=float(f.f_blocks-f.f_bfree)*100.00/float(f.f_blocks)
>>> x
41.05497734176585
>>> x=float(f.f_blocks-f.f_bavail)*100.00/float(f.f_blocks)
>>> x
46.21781783775708
>>>

os v. posix ebből a szempontból mindegy.

Hát pedig matematikailag a pyton-nak van igaza akárhogy is nézem: ha a df számait használom (240972 total block - 129600 available block) akkor abból pedig 46.2178% jön ki, nem 44%:
$ echo "scale=4;((240972-129600)*100)/240972"|bc
46.2178

Nézd meg, hogy másik FS-re is hasonló anomáliák jönnek e ki, mert a df nálad (ne kérdezd miért), de mintha valamit nem jól mutatna/számolna.
____________________________________
Az embert 2 éven át arra tanítják hogyan álljon meg a 2 lábán, és hogyan beszéljen... Aztán azt mondják neki: -"Ülj le és kuss legyen!"..

Ez ext2, a / ext4-en van, de egyik sem magyarázható kerekítési hibával. :(
Na mindegy, majd kiderül előbb-utóbb, hogy mi van.

update: mégis a fs volt a bűnös...


#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on Aug 3, 2014

@author: haazee
'''
import os

def get_free_space(fs):
st=os.statvfs(fs)
total=float(st.f_blocks*st.f_frsize)+float(st.f_bfree*st.f_frsize)-float(st.f_bavail*st.f_frsize)
percent=round((total-float(st.f_bfree*st.f_frsize))*100/total)
return percent

print get_free_space('/boot')

Így már stimmel, csak a forráskód formázása itt a hupon nem tökéletes. Vagy csak én nem találom, hogyan kell használni.

https://github.com/haa-zee/python-sandbox/blob/master/probak/freeblocks…
Itt olvashatóbb. :)

Egyébként csak egy tune2fs -l /dev/sda1 kellett neki. Abból kiderült, hogy az f_bfree és az f_bavail közti eltérés épp megfelel a tune2fs kimenetében látható "reserved" sornak.

Sziasztok,

Ha legyártok mondjuk 9 fájlt így:

for i in `seq 1 9`; do touch $i; done

És utána úgy szeretném listázni őket, hogy az időben utoljára létrehozott ne látszódjon, akkor ezt hogyan lehet elérni?
Eddig az ls -l | tail -lel próbálkoztam:-(

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

Sziasztok,

Köszönöm az eddigi segítségeteket, nagyon tetszik ez a megoldás: touch {1..9} :-)

tesztelési célokra szeretnék létrehozni bizonyos mintázat alapján fájlokat, úgy hogy ez legyen a séma pl.:

20140901_blablablabla_1.jpg
20140901_blablablabla_2.jpg
20140901_blablablabla_3.jpg
20140901_blablablabla_4.jpg
...
20140901_blablablabla_9.jpg

Ezeken a teszt fájlokon próbálnám ki a scriptekkel kísérletezem egy teszt mappában.

Azt nem értem (-de tudom, hogy lehet és sejtem is, hogy a bash printf-fel), hogy hogyan lehet rávenni a bash-t, hogy a létrehozás előtt szórja be a "20140901_blablabla_" stringet az 1,2,3...9 elé:-(
De biztosna lehet awk val , meg sed del is, de én már akkor örülnék, hogyha az egyik módszert megérteném.

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"

hát ez szuper!! köszi! Vezető nullákkal is el lehet látni? Erre gondolok 01, 02, 03 ...10,11,12, a seq tud ilyet: seq -w 1 11

És ezt valahogy működésre lehet bírni?
touch YYMMDD_blablabla_{1..11}.jpg

-- Zoli ---

Lenovo T400 @ Crunchbang "Waldorf"