# 4. cvičení, 2005-03-16, Malá Strana
#
# $DevNullCZ: cviceni-04.reseni.txt,v 1.2 2005/04/01 08:43:48 jp Exp $
#

#---------------------------------------------------------------------
# regulární výrazy
#---------------------------------------------------------------------
(g1) vypište řádky s loginem ve tvaru xxxxNNNN, kde 'x' je písmeno,
'N' je číslo (výsledek 102)

## grep -e '^[[:alpha:]]\{4\}\([[:digit:]]\{4\}\):' /etc/passwd | wc -l

#---------------------------------------------------------------------# 
# find
#
# Pro procházení stromu adresářů, vybírání jednotlivých souborů
# podle různých podmínek a provádění akcí na ně.
#---------------------------------------------------------------------

(f1) Pomocí příkazu find(1) nalezněte ve stromu začínajícím v
/usr/local soubor "httpd.conf"

##  cd /usr/local
##  find . -name 'httpd.conf'
##
## nebo rovnou "find /usr/local -name 'httpd.conf'"

NOTE: není nutné používat -print, pokud si uvědomíte, že (viz man
find(1)):

-print  This primary always evaluates to true. It prints the pathname of
        the current file to standard output. If none of -exec, -ls,
        -print0, or -ok is specified, the given expression shall be
        effectively replaced by ( given expression ) -print.

==> tedy jakmile použíjete některý z exec, ls, print nebo ok, tak
defaultní výpis na konci se již NEPROVÁDÍ. Příklad na toto viz (fb).


(f2) Jako (f1), ale zbavte se těch chybových hlášek oznamujících
"permission denied"

##  find /usr/local -name 'httpd.conf' 2>/dev/null

NOTE: "-name" se týká pouze samotného jména souboru, tedy netýká se
případné cesty k němu !!! Zkuste si například stejným způsobem najít
celé jméno "etc/apache2/httpd.conf" - nejde to.


(f3) Ve stejném adresáři mi najděte všechny konfigurační soubory
(soubory končící na ".conf").

## find /usr/local -name '*.conf' 2>/dev/null

Hint: použijte jednoduchý regulární výraz


(f3b) Najděte a vypište všechny adresáře, tedy TYP vypisovaného
souboru je adresář...

## find . -type d 2>/dev/null


(f4) Jako (f3), ale nechci tam mít konfiguráky, které začínají na
"mib2c"

Hint: "-not"

## find . -name '*.conf' -not -name 'mib2c*' 2>/dev/null


(f5) Jako (f4), ale pro každý takový soubor chci vypsat počet jeho
žádků. Výstup příkazu wc nemusíte dále upravovat.

Hint: "-exec", {}

Pozor na to, že konec vstupu do "-exec" musíte ukončit pomocí "\;",
jinak vám ten středník sežere shell (PROČ ?)

## find . -name '*.conf' -not -name 'mib2c*' -exec wc -l {} \; 2>/dev/null


(f6) Spočítejte mi soubory, které se v podstromu /usr/local změnily
behěm posledních 24 hodin. Odhaduji, že by to mohlo být kolem 70
souborů.

Hint: vyberte některou z "time" možnostní příkazu find

## find . -ctime 1 2>/dev/null | wc -l

#---------------------------------------------------------------------
# xargs
#
# Vytváří seznam argumentů a s nimi spustí zadaný příkaz.
#---------------------------------------------------------------------
MOTIVACE:

- příkaz "jot" vytváří sekvence čísel, tedy "jot 10" vypíše
  posloupnost od 1 do 10.
- zpětné uvozovky na příslušné místo ,,vloží'' výstup příkazu, který
  je uveden mezi zpětnými uvozovkami, tedy:

[KOLEJ-MAIL:pechanec]~/tmp/xargs$ /bin/echo `jot 10`
1 2 3 4 5 6 7 8 9 10

  (znaky nových řádků se zde nahradí mezerami, to vemte nyní jako fakt)

  NOTE: v následující ukázce MUSÍTE použít "/bin/echo" místo "echo",
  protože echo je vestavěný příkaz shellu, který má méně omezení

- z toho vyplývá, že "/bin/echo `jot 15000`" by vám mělo vypsat
  řádku s 15-ti tisíci čísly. Není tomu tak, protože jsme přesáhli
  maximální možný počet argumentů na příkazové rádce:

[KOLEJ-MAIL:pechanec]~/tmp/xargs$ /bin/echo `jot 15000`
-bash: /bin/echo: Argument list too long

- řešením v takové chvíli je právě třeba xargs (ale nejen v těchto
  situacích):

[KOLEJ-MAIL:pechanec]~/tmp/xargs$ jot 15000 | xargs /bin/echo


(a1) Vytvořte soubory test1 až test10

Hint: option '-I', '-L'

## jot 10 | xargs -L1 -I% touch test%

(a2) Teď tyto soubory přejmenujte na xtest1 až xtest10. Jako vstup
do xargs zkuste jot i ls.

## jot 10 | xargs -L1 -I% mv test% xtest%
##
## nebo třeba:
##
## ls test* | xargs -L1 -I% mv % x%


#---------------------------------------------------------------------
# join
#---------------------------------------------------------------------

(ja) Udělejte databázový join na soubory /etc/passwd a /etc/group
přes číslo skupiny.

Hint: man join(1)

## join -t: -1 4 -2 3 /etc/passwd /etc/group

#---------------------------------------------------------------------
# další příklady na find
#---------------------------------------------------------------------
(fa) V podstromu /usr/local prohledejte konfigurační soubory
(*.conf) a zjistěte, kde je řetězec "standalone"). Chci výpis, kde
bude u každé řadky vidět, v jakém souboru byl řetězec nalezen.

Hint: když zadáte grepu na příkazovou řádku více než jeden soubor
jako vstup, jeho výstup je vždy ve formátu "<filename>:<line>" i
kdyby byl řetězec nalezen vždy jen v jednom souboru. Dobrým trikem
je proto použít jako druhý soubor prázdný soubor - třeba "/dev/null"

## find . -name '*.conf' -exec grep -e standalone {} /dev/null \; 2>/dev/null

(fb) Vypište soubory v podstromu /usr/local, které mají velikost 4KB
(respektive větší než 3.5KB a menší nebo rovno než 4KB) a končí na
".conf" nebo na ".8". Vypište o nich podrobnosti ("ls"). Oveřte si v
manuálových stránkách, že operátor AND má vetší prioritu než OR !!!

Hint: použijte závorkování v parametrech příkazů find

## find /usr/local -size 8 -and \( -name '*.conf' -or -name '*.8' \) -ls 2>/dev/null
##
## uvědomte si, proč jsou zde závorky důležité !!! A uvědomte si
## prioritu operátorů !!! Tedy následující příkaz:
##
## find /usr/local -name '*.conf' -or -name '*.8' -size 8 -ls 2>/dev/null
##
## se nevykoná jako:
##
## find /usr/local -name \( '*.conf' -or -name '*.8' \) -and -size 8 -and -ls 2>/dev/null
##
## ale jako:
##
## find /usr/local -name '*.conf' -or \( \( -name '*.8' -and -size 8 \) -and -ls \) 2>/dev/null
##
## což zároveň znamená, že předchoží zápis a následující zápis dají
## ROZDÍLNÉ výsledky !!!
##
## find /usr/local -name '*.conf' -ls -or \( \( -name '*.8' -and -size 8 \) -and -ls \) 2>/dev/null


(fc) Co se vám ještě může hodit:

-x      neleze do jiných filesystémů než je ten, ze kterého find
        spouštíte

-d      prohledává do šířky; abyste viděli rozdíl, stačí si dát
        "find ." a "find -d ." na nějakém malém adresářovém
        podstromu