Bash: Porovnání verzí

Z GeoWikiCZ
m (doplněna zmínka o příkazech basename a dirname)
 
(Není zobrazeno 12 mezilehlých verzí od stejného uživatele.)
Řádek 1: Řádek 1:
'''Bash''' je shell, tj. příkazový interpret, který je součástí operačního systému GNU.
'''Bash''' je shell, tj. příkazový interpret, který je součástí operačního systému GNU.  Ve skriptech v jazyce bash označuje výraz <tt>$0</tt> adresář a jméno skriptu. Pro získání adresáře ze kterého byl skript spuštěn slouží příkaz <tt>dirname $0</tt>, pro získání jména skriptu bez adresáře <tt>basename $0</tt>.


== Ukázky a příklady ==  
== Ukázky a příklady ==  
=== Dávkový editor sed ===
Odstranění mezer na konci řádků.
<pre>
sed -i -e 's/[[:space:]]*$//'  soubor(y)
</pre>


=== Příkazy find, sed, grep, case, echo a cmp ===
=== Příkazy find, sed, grep, case, echo a cmp ===
Řádek 38: Řádek 45:
</pre>
</pre>


=== Příkazy for, if, find, md5sum, awk, cmp a sqlite3 ===
=== Příkazy for, if, find, grep, md5sum, awk, cmp a sqlite3 ===


Skript prohledá zadné akresáře a vytvoří seznam duplicitní souborů, tj. identických souborů  nacházejících se v různých adresářích. Implicitně hledá duplicity v běžném adresáři. Pro všechny nalezené soubory nejprve skript vypočítá jejich kontrolní součty (<code>md5sum</code>), v databázi <code>sqlite</code> je agreguje, soubory se stejnými md5 součty porovná příkazem <code>cmp</code> a vytvoří jejich seznam.
Skript prohledá zadné akresáře a vytvoří seznam duplicitní souborů, tj. identických souborů  nacházejících se v různých adresářích. Implicitně hledá duplicity v běžném adresáři. Pro všechny nalezené soubory nejprve skript vypočítá jejich kontrolní součty (<code>md5sum</code>), v databázi <code>sqlite</code> je agreguje, soubory se stejnými md5 součty porovná příkazem <code>cmp</code> a vytvoří jejich seznam.


Soubory se jmény obsahujícími mezery a znaky ( a soubory v adresarich <code>cvs</code> jsou ignorovány.
<pre>
<pre>
#!/bin/bash
#!/bin/bash
Řádek 82: Řádek 91:
       df AS b  
       df AS b  
       ON a.md5 = b.md5 AND a.file < b.file
       ON a.md5 = b.md5 AND a.file < b.file
  ORDER BY a.md5;
  ORDER BY a.file;
EOF
EOF


Řádek 93: Řádek 102:
rm -f $LIST.*
rm -f $LIST.*
</pre>
</pre>
=== Úklid pracovních adresářů (case, if, find, xargs) ===
Skript provádí úklid pracovních adresářů, může být pravidelně spouštěn v cronu (na serveru) nebo při startu systému (na osobním počítači). Soubory a adresářě starší než jeden týden přesouvá do adresáře .null, kde jsou smazány po dvou měsících.
<pre>
#!/bin/bash
### BEGIN INIT INFO
# Provides:          uklid
# Required-Start:    $remote_fs $syslog
# Required-Stop:    $remote_fs $syslog
# Default-Start:    2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Uklid pracovniho adresare
# Description:      This file should be placed in /etc/init.d
#                    1) cp uklid /etc/init.d
#                    2) update-rc.d  uklid defaults
#
### END INIT INFO
#
#
case "$1" in
  start)
    echo "Starting script uklid "
      # uklid pracovniho adresare
      # -----------------------------------------------------------
      NULL=/home/cepek/.null
      if ! test -d $NULL; then mkdir $NULL; fi
       
      if ! test -d $NULL/`date -I` ; then
          mkdir    $NULL/`date -I`
      fi
       
      WORKDIR="/home/cepek/work"
      touch      $WORKDIR     
      for WORK in $WORKDIR
      do
        if [ "xxx`find $WORK -maxdepth 1 -mtime +6 -print0`xxx" != "xxxxxx" ];
        then 
        find  $WORK -maxdepth 1 -mtime +6 -print0 | xargs -0 mv -v -t $NULL/`date -I`;
        fi
       
      done
      find $NULL -maxdepth 1 -mtime +60 -print0 | xargs -0 rm -rfv
    ;;
  stop)
    echo "Stopping script uklid"
    ;;
  *)
    echo "Usage: /etc/init.d/uklid {start|stop}"
    exit 1
    ;;
esac
exit 0
</pre>
=== Porovnání souborů ze dvou adresářů (find, grep, sed,  diff) ===
Jména prohledávaných adresářů jsou uvedena explicitně, mohou být pochopitelně nahrazena pozičními parametry $1 a $2. Znak % je v příkazu sed použit proto, aby nekolidoval s oddělovačem jmen souborů a adresářů /.
<pre>
#!/bin/bash
TRG=gama
SRC=~/GNU/ro-gama
for i in $(find $SRC -type f | grep -v CVS | sed s%$SRC%%)
do
    diff $SRC/$i $TRG/$i
done
</pre>
=== Výpočet kontrolních součtů pro soubory s mezerami (find, args, md5sum) ===
Příkazem <tt>find</tt> vyhledáme v zadaném adresáři všechny soubory a vypočteme pro ně kontrolní součty. Protože soubory mohou obsahovat mezery (a případně další ''bílé znaky'') použijeme parametr <tt>-print0</tt>, který na výstupu místo konce řádku LF používá znak NULL. Následné zpracování zajistí program <tt>xargs</tt>.
find ''adresář'' -type f -print0 | xargs -0 md5sum


== Externí odkazy ==
== Externí odkazy ==

Aktuální verze z 29. 11. 2010, 09:03

Bash je shell, tj. příkazový interpret, který je součástí operačního systému GNU. Ve skriptech v jazyce bash označuje výraz $0 adresář a jméno skriptu. Pro získání adresáře ze kterého byl skript spuštěn slouží příkaz dirname $0, pro získání jména skriptu bez adresáře basename $0.

Ukázky a příklady

Dávkový editor sed

Odstranění mezer na konci řádků.

sed -i -e 's/[[:space:]]*$//'  soubor(y)

Příkazy find, sed, grep, case, echo a cmp

Bash skript pro porovnání dvou adresářů s ošetřením jmen souborů obsahujících mezery, odfiltrováním skrytých souborů a rotující vrtulkou jako indikátorem průběhu zpracování (ukázka použití příkazu case).

#!/bin/bash

SRC=amonit-2009-04-29
TRG=amonit-CD

FILES=$(cd $SRC && find -type f | sed s/\ /?/g | grep -v /\\. )

c=-
for i in $FILES
do
    case $c in 
    -)
    c=\\
    ;;
    \\)
    c=\|
    ;;
    \|)
    c=/
    ;;
    /)
    c=-
    ;;
    esac
    echo -en "\b$c"

    cmp -l $SRC/$i $TRG/$i
done

Příkazy for, if, find, grep, md5sum, awk, cmp a sqlite3

Skript prohledá zadné akresáře a vytvoří seznam duplicitní souborů, tj. identických souborů nacházejících se v různých adresářích. Implicitně hledá duplicity v běžném adresáři. Pro všechny nalezené soubory nejprve skript vypočítá jejich kontrolní součty (md5sum), v databázi sqlite je agreguje, soubory se stejnými md5 součty porovná příkazem cmp a vytvoří jejich seznam.

Soubory se jmény obsahujícími mezery a znaky ( a soubory v adresarich cvs jsou ignorovány.

#!/bin/bash

LIST="/tmp/$$-duplicate-files"
rm -f $LIST.*

if [ "$1" == "" ]; then
DIRS=.
else
DIRS="$1 $2 $3 $4 $5 $6 $7 $8 $9"
fi


cat <<EOF >$LIST.awk
{ print "INSERT INTO df VALUES ('" \$1 "', '" \$2 "');" }
EOF

sqlite3 $LIST.db "CREATE TABLE df (md5 char(32), file text)";

for d in $DIRS
do
    for f in $(find $d -type f | grep -v "\ " | grep -v "(" | grep -v \/CVS\/ )
    do
        md5sum $f | awk -f $LIST.awk | sqlite3 $LIST.db
    done
done


cat <<EOF > $LIST.sql
DELETE FROM df WHERE md5 IN 
   (SELECT md5
      FROM df
     GROUP BY md5
    HAVING count(file) = 1);

SELECT a.file, b.file
  FROM df AS a
       JOIN 
       df AS b 
       ON a.md5 = b.md5 AND a.file < b.file
 ORDER BY a.file;
EOF

cat <<EOF > $LIST.awk
{print "if cmp -s " \$1 " " \$2 " ; then echo cmp " \$1 " " \$2 "; fi" }
EOF

sqlite3 $LIST.db < $LIST.sql | awk -F \| -f $LIST.awk | bash

rm -f $LIST.*

Úklid pracovních adresářů (case, if, find, xargs)

Skript provádí úklid pracovních adresářů, může být pravidelně spouštěn v cronu (na serveru) nebo při startu systému (na osobním počítači). Soubory a adresářě starší než jeden týden přesouvá do adresáře .null, kde jsou smazány po dvou měsících.

#!/bin/bash
### BEGIN INIT INFO
# Provides:          uklid
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Uklid pracovniho adresare
# Description:       This file should be placed in /etc/init.d
#                    1) cp uklid /etc/init.d
#                    2) update-rc.d  uklid defaults
#
### END INIT INFO
#
#

case "$1" in
  start)
    echo "Starting script uklid "

      # uklid pracovniho adresare
      # -----------------------------------------------------------

      NULL=/home/cepek/.null
      if ! test -d $NULL; then mkdir $NULL; fi
        
      if ! test -d $NULL/`date -I` ; then
          mkdir    $NULL/`date -I`
      fi
        
      WORKDIR="/home/cepek/work"
      touch       $WORKDIR      
      for WORK in $WORKDIR
      do

        if [ "xxx`find $WORK -maxdepth 1 -mtime +6 -print0`xxx" != "xxxxxx" ]; 
        then  
        find  $WORK -maxdepth 1 -mtime +6 -print0 | xargs -0 mv -v -t $NULL/`date -I`;
        fi
        
      done

      find $NULL -maxdepth 1 -mtime +60 -print0 | xargs -0 rm -rfv
    ;;
  stop)
    echo "Stopping script uklid"

    ;;
  *)
    echo "Usage: /etc/init.d/uklid {start|stop}"
    exit 1
    ;;
esac

exit 0

Porovnání souborů ze dvou adresářů (find, grep, sed, diff)

Jména prohledávaných adresářů jsou uvedena explicitně, mohou být pochopitelně nahrazena pozičními parametry $1 a $2. Znak % je v příkazu sed použit proto, aby nekolidoval s oddělovačem jmen souborů a adresářů /.

#!/bin/bash

TRG=gama
SRC=~/GNU/ro-gama

for i in $(find $SRC -type f | grep -v CVS | sed s%$SRC%%)
do
    diff $SRC/$i $TRG/$i
done

Výpočet kontrolních součtů pro soubory s mezerami (find, args, md5sum)

Příkazem find vyhledáme v zadaném adresáři všechny soubory a vypočteme pro ně kontrolní součty. Protože soubory mohou obsahovat mezery (a případně další bílé znaky) použijeme parametr -print0, který na výstupu místo konce řádku LF používá znak NULL. Následné zpracování zajistí program xargs.

find adresář -type f -print0 | xargs -0 md5sum

Externí odkazy