Cátedra: Osvaldo Clua
Fecha: Primer recuperatorio - Segundo Cuatrimestre 2002
Día: 12/11/2002
Tema: UNIX
Se tiene un directorio de Input con una serie de archivos a procesar. Programar un comando que grabe en un directorio de output un archivo con todos los registros de todos los archivos <cualquier nombre>.txt del directorio de Input, considerando que:
El comando debe comtemplar las siguientes opciones:
#!/bin/bash RecorrerDir() { #$1 = Path que tengo que recorrer y en el que arranca posicionada la funcion for arch in * do if [ -d "$1/$arch" ] # Si arch es un directorio, entra en él (esto incluye . y ..) then cd "$1/$arch" RecorrerDir "$PWD" # Se llama a sí mismo (recursivamente else file=$(echo $arch | grep '.*\.txt$') # Si es ".txt" asigno nombre a file if [ "${file:-1}" != '1' ] # Me fijo si comando anterior asignó algo a file then ValidarArch "$file" # Valida (<8 campos) y procesa fi fi done } ValidarArch() { # Valida que el archivo tenga <8 campos y si el campo coincide con el filname (parametro) llama a AceptarReg #$1 = Nombre del archivo (incluye ".txt") IFS=' ' # Interanal File Separator ($* es su primer char). Separador de campos local rechazar='0' # Con local defino una variable invisible fuera del scop de la funcion scope. Rechaza o no el archivo for reg in `cat $1` # for variable in lista. cat va devolviendo línea a línea (registro). Recordar que $1 en esta funcion es $file (PRIMER parámetro de la recibido por la funcion, semejante a argv[1] con funcion main) do if [ "$rechazar" = '0' ] # Si no se rechaza (rechaza falso)... then declare -i cantcampos # declaro variable entera cantcampos. ¿let cantcampos=0 no da igual? cantcampos=$(echo $reg | grep -o ';' | wc -l) # cuenta campos: del reg, saca --only-matching con ';' y luego los cuenta ¿-l cuenta no líneas!? let cantcampos=$cantcampos+1 # cantcampos++ if (($cantcampos > 8)) then campo2=$(echo $reg | cut -d ';' -f 2) # hermoso comando cut, saca el field 2, campos separados por ';' if [ "$campo2" = "$1" ] # Compara 2do field con nombre de arch (param), pedido en ítem 1 enunciado then AceptarReg "$reg" # campo2==coincide con el filename, acepta fi else rechazar='1' # rechazo el registro fi fi done if [ "$rechazar" = '1' ] then RechazarArch "$1" # Si el archivo fue rechazado... else let aceptados=$aceptados+1 # aceptados++ fi if [ "$delete" = 'S' ] # Si fue elgida la opción -w (era -e), borra el archivo then rm $1 fi } AceptarReg() { #$1 = Registro echo $reg >> "$path/logresumen" # Append del registro (con su \n al final) } RechazarArch() { #$1 = Nombre del archivo echo "Archivo $1 rechazado" >> "$path/logerror" let rechazados=$rechazados+1 } # COMIENZO DEL SCRIPT path_anterior="$PWD" # Guardo el directorio corriente path="$PWD" # Guardo el directorio corriente while [ -n "$(echo $1 | grep '^-')" ] # mientras los parámetros comiencen con "-"... (excepto path, por eso el shift) do case $1 in # pruebo casos tomando "argv[1]". Notar que está definiendose un caso O EL OTRO (no varios al mismo tiempo). -d) path="$2" # si -d después viene el path, $2 shift;; -a) all='S';; # si la opción fue elegida, defino variable (all, recorrer subdirs) -w) delete='S';; # No me pregunten por que, pero con -e no entra aca -f) addtolog='S' # si la opción fue elegida, defino variable ("final", agrego de msgs a logs) declare -i aceptados=0 # Uso declare pq son enteros declare -i rechazados=0;; * ) echo 'USO: parcial [-d <path>] [-a] [-w] [-f]' # Si no se usan modificadores, mensaje y error (exit 1) exit 1;; esac shift done # fin del while, ahora sé qué tengo que hacer según el caso (mediante variables definidas cd "$path" # Voy al path (en el que ya estoy.... cof cof if [ "$all" = 'S' ] # recordar que eq es para comparar strings (al reves de Perl) then RecorrerDir "$path" # Si ALL, recorro todos, else # else sólo el actual for arch in * # for variable in lista. (variable "arch"). Va poniendo en arch cada elemento de lista (en este caso c/n d arch) do file=$(echo $arch | grep '.*\.txt$') # arch tiene el archivo actual del for, grep lo devuelve si termina en .txt if [ "${file:-1}" != '1' ] # Si el grep seteo la variable file con algo... OBS: [ -z $file ] debería ser == then ValidarArch "$file" # me fijo si valida (si tiene 8 campos). Si es así, procesa fi done fi