-1

I'm working writing a bash script and I am becoming crazy with a mysterious loop.

I need to seek for a concrete code inside a text file (codigos.txt) that contains many codes and, if the code is found, I need to seek for the next one (siguienteCodigo++) until the code is not found, so I've written the next while loop (where $siguienteCodigo is the variable containing the code to search and $rutaOrigen is the path to the file containing the codes, codigos.txt):

while grep -F "$siguienteCodigo" "$rutaOrigen/codigos.txt"; do
    let siguienteCodigo++
done

But when I execute the script, my surprise is that it seems to find the codes but the codigos.txt file is removed!

Below is the complete script:

#!/bin/bash
#
################################################################################
# SCRIPT PARA CODIFICAR RECURSIVAMENTE TODAS LAS FOTOGRAFÍAS DE LOS ARTÍCULOS  #
# Y REGISTRARLAS EN UNA HOJA DE CÁLCULO DE MICROSOFT EXCEL                     #
################################################################################
#
# Extraemos el día, mes, año, hora, minuto y segundo
day="$(date +%d)"
month="$(date +%m)"
year="$(date +%Y)"
hour="$(date +%H)"
minute="$(date +%M)"
second="$(date +%S)"
# Extraemos la ruta de origen, donde se ejecuta el script
rutaOrigen="$(pwd)"
# Recorremos todos los directorios listados recursivamente, a partir de la ruta
# de origen
for d in $(ls -R | grep "^\." | sed 's/://'); do
    # Cambiamos al directorio
    cd "$d"
    # Buscamos cuál es el último artículo codificado
    ultimoCodigo=$(printf "%08d" "0")
    # Recorremos todos los archivos que nos interesa listar, que son todos
    # los archivos con extensión .jpg .JPG y .txt
    for i in $(ls *.jpg *.JPG *.txt); do
        # Extraemos el nombre del archivo, sin extensión
        case "${i##*.}" in
            "jpg")
                fotoActual="$(basename -s ".jpg" "$i")";;
            "JPG")
                fotoActual="$(basename -s ".JPG" "$i")";;
            "txt")
                fotoActual="$(basename -s ".txt" "$i")";;
        esac
        # Extraemos los 8 primeros carácteres del archivo, que
        # corresponderán al "código 8" del artículo
        codigo8=$(expr substr "$fotoActual" 1 8)
        # Si los 8 primeros carácteres del archivo forman un numérico
        # entero y éste es mayor que el último "codigo 8" guardado,
        # inicialmente iniciado a 0...
        if [[ $codigo8 =~ ^[0-9]+$ ]] && (( codigo8 > ultimoCodigo )); then
            # Guardamos el "código 8" actual como el último código,
            # es decir, como el último artículo codificado
            ultimoCodigo=$(printf "%08d" "$codigo8")
        fi
    done
    # Volvemos a recorrer todos los archivos que nos interesa listar, esta
    # vez para codificar los que no están codificados, es decir, los que
    # siguen al último artículo codificado
    for i in $(ls *.jpg *.JPG *.txt); do
        # Extraemos el nombre del archivo, sin extensión
        case "${i##*.}" in
            "jpg")
                fotoActual="$(basename -s ".jpg" "$i")";;
            "JPG")
                fotoActual="$(basename -s ".JPG" "$i")";;
            "txt")
                fotoActual="$(basename -s ".txt" "$i")";;
        esac
        # Extraemos los 8 primeros carácteres del archivo, que
        # corresponderán al "código 8" del artículo
        codigo8=$(expr substr "$fotoActual" 1 8)
        siguienteCodigo=$(($ultimoCodigo + 1))
        # Si los 8 primeros carácteres del archivo forman un numérico
        # entero y éste es mayor que el último "código 8" guardado...
        if [[ $codigo8 =~ ^[0-9]+$ ]] && (( codigo8 <= ultimoCodigo )); then
            :
        else
            while grep -F "$siguienteCodigo" "$rutaOrigen/codigos.txt"; do
                let siguienteCodigo++
            done
            rutaActual="$(pwd)"
            carpetaActual="$(basename "$rutaActual")"
            caracteresCarpeta=$(expr length "$carpetaActual")
            descripcion="$(expr substr "$carpetaActual" 10 $caracteresCarpeta)"
            rutaActual="$(echo -e "$rutaActual" | sed 's/\//\\/g' | sed 's/\\media\\sf_E_DRIVE/E:/')"
            let ultimoCodigo++
            newFile=$(printf "%08d_${day}-${month}-${year}_${hour}-${minute}-${second}.jpg" "$siguienteCodigo")
            mv -- "$i" "$newFile"
            echo -e "$siguienteCodigo\t$rutaActual\t$descripcion\t$day/$month/$year\t$hour:$minute:$second" | awk -F '\t' '{print $1,$2,$3,$4,$5}' OFS='\t' >> "$rutaOrigen/registroarticulos.xls"
        fi
    done
    cd "$rutaOrigen"
done
echo "Se creó una hoja de registro en $rutaOrigen/registroarticulos.xls"
echo "Todas las fotografías fueron codificadas correctamente :)"
exit 0
  • 1
    The issue will be difficult to reproduce by anyone but you. Nothing in the code suggests that a file could be removed. What you could try is to remove the loop from your script, re-run the script and check if the file still gets removed. – Dmitry Grigoryev Oct 2 '15 at 10:57
  • 2
    You execute a mv in your script while iterating over various files including *.txt. Could it be that you are accidentally moving/renaming codigos.txt? You can call mv with -v to produce some debugging output. – scai Oct 2 '15 at 11:05
4

Your script is working on .JPG, .jpg and .txt files.

The codigos.txt file is renamed in the first run on the . directory derived from the $(ls -R | grep "^\." | sed 's/://') output.

In a testrun on my machine the file codigos.txt was renamed to 00000002_02-10-2015_13-18-59.jpg

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.