LX-SCR-INFO-file-io
updated 7/27/10 00:14

file-io

Eigenlijk doen we al een hele tijd aan file i/o:


Files schrijven kan je met een simpele redirect > of >> en dat doen we ook regel per regel met echo, en woord voor woord met printf.

Tenslotte zijn er nog een heleboel tools, met als belangrijkste sed, om tekstregels en woorden in te voegen, te verwijderen, of te vervangen.

We beginnen met enkele eenvoudige voorbeelden (met dank aan Koen Lefever)

  1. Een file aanmaken en er naartoe schrijven
     
    Een file openen om er naartoe te schrijven doen we met  >
    De file wordt dan eerst (opnieuw) geïnitialiseerd. En dan met karakters, en layout elementen (cr, lf, tab, space) volgeschreven.
    Volgende tekstregels voegen we toe met  >>

    In het volgende voorbeeld schrijven we een script "maaktext" dat een bestand "tekstje" aanmaakt met daarin de volgende regels:

    Dit is de eerste regel
    Dit is de tweede regel
    Dit is regel drie
    Dit is de laatste regel

    #!/bin/bash
    #
    # maaktext: maakt het bestand tekstje
    #
    echo "Dit is de eerste regel" >  tekstje
    echo "Dit is de tweede regel" >> tekstje
    echo "Dit is regel drie"      >> tekstje
    echo "Dit is de laatste regel">> tekstje
    exit 0

    De output is als volgt:

    $ maaktext
    $ ls -l tekstje
    -rw-r--r-- 1 koen users 88 2010-07-25 18:38 tekstje
    $ cat tekstje
    Dit is de eerste regel
    Dit is de tweede regel
    Dit is regel drie
    Dit is de laatste regel

  2. more fun: parameter shift, exit status, tee

    In het volgende voorbeeld "uhavbenhckd" schrijven we in de home directories van alle gebruikers die als argument achter de naam van dit script worden ingetikt. We lezen dus één voor één alle parameters. Dat doen we op een iets andere manier dan we zouden verwachten. Het shift commando verplaatst parameters naar links ($2 komt in $1 terecht, $3 in $2, enzoverder)

    Bovendien controleren we de exit status van onze schrijfopdracht. De exit status wordt opgevraagd met $?  Indien $? nul is, is alles goed verlopen, maar indien niet nul, is er een error opgetreden.

    We plaatsen dan een file op de Desktop van de slachtoffers, met als naam "DEFACED" en als inhoud "U h4v3 b33n h4x0red!!!"

    #!/bin/bash
    #
    # uhavbenhckd: voegt een bestand toe op de desktop
    #              van de users in $1 en volgende
    #
    function timestamp {
        echo $(date +"%Y%m%d%H%M%S")
    }

    logfile=hacked.log

    echo $(timestamp)\: -------------------------------------------- >> $logfile
    echo $(timestamp)\: $0 was initiated ... >> $logfile

    while [ $# -gt 0 ] # zolang er nog argumenten zijn ...
    do
           # zijn uitroeptekens speciale tekens -> \!\!\!
           # we willen de error messages sturen naar de logfile, daarom haakjes
         ( echo "U h4v3 b33n h4x0red\!\!\!" > /home/$1/Desktop/DEFACED ) 2>> $logfile

           # nu testen we de exit status
         if [ "$?" -eq "0" ]
           # tee brengt output op scherm en in de file, tee -a doet een append

         then echo $(timestamp)\: user $1 was hacked succesfully | tee -a $logfile
         else echo $(timestamp)\: user $1 was protected by darth vadar | tee -a $logfile
         fi
           # en nu schuiven we de parameters op naar links

         shift
    done


    output:

    $ uhavbenhckd geert koen bert root
    20100725234118: user geert was protected by darth vadar
    20100725234118: user koen was protected by darth vadar
    20100725234118: user bert was hacked succesfully
    20100725234118: user root was protected by darth vadar


    $ cat hacked.log
    20100725234118: --------------------------------------------
    20100725234118: /home/bert/bin/uhavbenhckd was initiated
    /home/bert/bin/uhavbenhckd: line 14: /home/geert/Desktop/DEFACED: No such file or directory
    20100725234118: user geert was protected by darth vadar
    /home/bert/bin/uhavbenhckd: line 14: /home/koen/Desktop/DEFACED: No such file or directory
    20100725234118: user koen was protected by darth vadar
    20100725234118: user bert was hacked succesfully
    /home/bert/bin/uhavbenhckd: line 14: /home/root/Desktop/DEFACED: No such file or directory
    20100725234118: user root was protected by darth vadar

    $ ls ../Desktop
    6_grafische_schermen_op_SuSE
    802-lan-standards
    Bruce_Perens
    DEFACED
    dell_lat505


    $ cat ../Desktop/DEFACED
    U h4v3 b33n h4x0red\!\!\!


    Er is toch iets misgegaan met die uitroeptekens !!!

  3. oefeningen

    1. Schrijf een script met als naam "addprofile" dat je .profile opent en er de volgende regels aan toe voegt:
      export PATH=$PATH:~/bin
      alias cls="clear"
      alias ll="ls -al"
      De quotes moeten er ook in op één of andere manier ...

    2. Schrijf een script met als naam "creagebr" dat een reeks gebruikersnamen verwacht als argumenten en deze gebruikers dan aanmaakt. Geef ze het paswoord "sdf12345". Test de exit status van het commando useradd. Schrijf per aangemaakte gebruiker in een logbestand /var/log/creagebr dat die gebruiker toegevoegd is, en per fout dat er een fout is opgetreden. Stuur dezelfde output op scherm.

  4. files lezen

    Files lezen doen we al een tijdje met while. Toch nog een voorbeeld:

    We schrijven een script "numberline" dat een bestandsnaam krijgt als argument (en een bestandsnaam vraagt als er geen argument gegeven wordt). Het bestand wordt met regelnummers afgedrukt.

    #!/bin/bash
    #
    # numberline: drukt regelnummers af voor tekstregels van een bestand
    #
    if [ $# -eq 0 ]
    then
         read -p "Bestandsnaam: " filenaam
    else
         filenaam=$1
    fi
    teller=0
    while read lijn
    do
         (( teller++))   # teller = teller + 1 (bash wiskunde lijkt op C)
         echo "$teller: $lijn"
    done < $filenaam
    exit 0

    $ numberline tekstje
    1: Dit is de eerste regel
    2: Dit is de tweede regel
    3: Dit is regel drie
    4: Dit is de laatste regel


    Maar het volgende 1-regel-script werkt ook (nu ja, bijna ... :-)

    #!/usr/bin/nl
    # nummerlijn: drukt regelnummers af voor tekstregels van een bestand

    $ nummerlijn tekstje
         1    #!/usr/bin/nl
         2    Dit is de eerste regel
         3    Dit is de tweede regel
         4    Dit is regel drie
         5    Dit is de laatste regel


    Maar we hebben eigenlijk helemaal geen script nodig:

    $ nl tekstje
         1    Dit is de eerste regel
         2    Dit is de tweede regel
         3    Dit is regel drie
         4    Dit is de laatste regel

  5. oefeningen

    1. Schrijf een script met als naam "achterstevoren" dat een bestand regel per regel inleest in een array en vervolgens achterstevoren afdrukt.

    2. Schrijf een script met als naam "tmpback" dat een pad naar een folder vraagt en dan een tar-backup van die folder in /tmp zet. De backup is een tar.gz file van de ingegeven folder. De tar.gz filenaam is hetzelfde als de pathnaam, waarbij slashes zijn vervangen door underscores. Redirect de output van tar naar een logbestand met als naam tmpback.log

  6. exec ...

    Soms is het nodig verschillende files tegelijkertijd te lezen. Je kan dan een fd-nummer (file descriptor) aan een file geven (een integer groter dan 5) en werken met de volgende syntax:

    #Open file $1 for reading to SHARE_LINE
     exec 10<$configfile

    #initialize counter
     count=0

    #read file line per line in SHARE_LINE
     while read LINE <&10; do
        SHARE_LINE[$count]=$LINE
        ((count++))
     done
     echo 'Number of elements in sharedefinition file:' ${#SHARE_LINE[@]}
     echo

    #Close file
     exec 10>&-


    Meer over exec vind je op de volgende links:

    http://www.linuxjournal.com/content/reading-multiple-files-bash
    http://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/x13082.html