• Inicio
  • Blog
  • Creandolared
  • Buscar
  • Ingresar
  • Registrarse

    • Hack x Crack - Comunidad de Seguridad informática »
    • Programación »
    • Scripting »
    • Batch / Bash »
    • [SOLUCIONADO] Dudas con IFS en Bash
    ¿Quieres aprender de páginas web? Visita la comunidad Creandolared
    • Imprimir
    Páginas: [1]   Ir Abajo

    Autor Tema: [SOLUCIONADO] Dudas con IFS en Bash  (Leído 3552 veces)

    Desconectado nikolat328

    • { L1 } Newbie
    • *
    • Mensajes: 59
      • Ver Perfil
    [SOLUCIONADO] Dudas con IFS en Bash
    « en: Agosto 12, 2013, 11:53:53 pm »
    Buenas!

    Tengo una consulta. Haciendo un script para copiar todas las carpetas y subcarpetas de un directorio me topé con el problema de que, como de mala costumbre usaba espacios para los nombres, las carpetas que tenían espacios no eran copiadas luego de pasar el siguiente comando porque las imprimía con el espacio:

    Código: [Seleccionar]
    ls -p | grep /
    Leí en algunos lugares que seteando el Internal Field Separator en:

    Código: [Seleccionar]
    IFS="$(echo -e "\n\r")"
    se cambiaba el caracter que se usaba como identificador de separación (si estoy diciendo burradas por favor corríjanme). Leí que generalmente por defecto es el espacio el que viene seteado en IFS pero no entiendo como el comando anterior hace que la cosa funcione (me toma cualquier carpeta por más que tenga espacios).

    Muchas gracias!
    « Última modificación: Agosto 20, 2013, 08:26:00 pm por k133 »
    En línea

    Desconectado k133

    • { L3 } Über
    • ***
    • Mensajes: 201
      • Ver Perfil
    Re:Dudas con IFS en Bash
    « Respuesta #1 en: Agosto 13, 2013, 03:35:59 am »
    El haberte topado con ese problema tiene un significado, y es que ese método que estabas usando no es el adecuado para esa tarea. Si pones el script te podría decir más.

    Y respecto a lo que dices del IFS es muy simple. Si ejecutas:
    Código: [Seleccionar]
    $ set | grep IFS
    IFS=$' \t\n'

    Verás los caracteres que se usarán como separador, el espacio, el TAB y el "salto de línea". Así que lo único que hace con ese comando es decirle que solo use como separador el fin de línea, es ese caso usa los caracteres '\n\r' que viene siendo el fin de línea usado en windows ( más bien sería al revés '\r\n' CR+LF ).

    Con lo cual fijándote en la salida del comando anterior, podrás apreciar que para coger solo el fin de línea, o lo que es lo mismo no coger como separador el espacio, basta con poner:
    Código: [Seleccionar]
    IFS=$'\n'

    Primeramente por que linux usa solo el '\n' para el salto de línea, y segundo por que no es necesario ejecutar un comando para asignárselo a una variable, que no esta mal pero a mi parecer queda feo.

    Si ejecutas por separado el comando veras que lo único que hace es imprimir un salto de línea:

    Código: [Seleccionar]
    $ echo -ne "\n\r"


    Te he añaido el -n porque el `echo' pone otro salto de línea al final y no imprime el texto como realmente es (de echo se recomienda el uso del comando `printf' en vez de el `echo'). Y si intentas imprimir el que te he dicho yo, pues te encuentras con que el resultado es el mismo:

    Código: [Seleccionar]
    $ echo -n $'\n'


    Solo que en el caso anterior haces que la variable tenga que tomar la salida de un comando, cuando en realidad puedes ponerlo tu mismo.
    « Última modificación: Agosto 13, 2013, 03:38:07 am por k133 »
    En línea
    Linux member #545609


    Desconectado nikolat328

    • { L1 } Newbie
    • *
    • Mensajes: 59
      • Ver Perfil
    Re:Dudas con IFS en Bash
    « Respuesta #2 en: Agosto 13, 2013, 06:31:54 am »
    Bueno, a partir de ahora voy a empezar a poner los códigos en los post.

    Código: [Seleccionar]
    #!/bin/bash

    ####################################################################
    ## Función para copiar todas las carpetas de un directorio a otro ##
    ## ##
    ## Usar $0 <directorio_de_origen> <directorio_de_destino> ##
    ####################################################################

    # Función para el copiado de carpetas
    folder_copy() {

    # Lista el directorio poniendo un renglón en cada carpeta
    dir=$(ls -p | grep /)

    # Recorro cada uno de los directorios
    for file in $dir
    do
    # Creo en el directorio destino un directorio con el nombre anterior
    mkdir $2/$file
    # Me cambio al directorio leído
    cd $file"/"
    # Aplico de nuevo la función copia sobre el nuevo directorio
    folder_copy $file $2/$file
    # Salgo del directorio leído
    cd ..
    done
    }

    # Si no se introducen bien los parámetros
    if [ $# -lt 2 ]
    then
    echo "Usar"
    echo " $0 <directorio_de_origen> <directorio_de_destino>"
    else
    # Me muevo al directorio del cual voy a copiar las carpetas
    cd $1

    # Notificación de inicio de copia de directorios
    echo -n $(notify-send 'Copia de directorios' "Iniciada!")

    # Guardo el Internal Field Separator previo y digo que sea "\n\r"
    IFS_prev="$IFS"
    IFS="$(echo -e "\n\r")"

    # Función recursiva para copiar las carpetas
    folder_copy $1 $2

    # Restauro el IFS anterior
    IFS="$IFS_prev"

    # Notificación de finalización de copia de directorios
    echo -n $(notify-send 'Copia de directorios' "Finalizada!");
    fi
    Ese es el código. No es para nada útil, pero lo hice porque necesitaba saber las carpetas que tenía en mi back up para poner las cosas nuevas en las carpetas correctas y después con el programa GoodSyn compararlas entre sí y actualizar cada una de las carpetas, pero si a alguien le sirve, más que bien :).

    Como andar anda, pero mi duda era justamente lo que me respondiste. No entendía por qué se le tenía que asignar el valor con un comando y tampoco entendía por qué tenía que ser "\n\r" y no solamente "\n" (todavía no probé si funciona de esta última manera pero supongo que sí).

    Para concluir un poco con la gran ayuda que me diste te pregunto las últimas 2 cosas:
    1) Poniendo
    Código: [Seleccionar]
    IFS=$' \t\n'lo que haces es decirle al programa que seleccione las cosas cosas para un for por ejemplo (leí que se llaman tokens, pero no quiero hablar sin saber) que estén separadas por un espacio O un tabulador O un enter? Por más que pongas esos 3 caracteres todos juntos en la definición anterior?

    2) Cuando pongo el comando
    Código: [Seleccionar]
    ls -p | grep / y luego de seleccionar
    Código: [Seleccionar]
    IFS=$'\n'lo que haría el programa es tomar como elementos aquellos que estén separados por '\n'? La verdad que esa parte del código la saqué de un ejemplo de internet y no entendí mucho lo que hacía, pero funcionaba.

    Muchas gracias!

    PD: Me salvaste la vida con el
    Código: [Seleccionar]
    $'\n'siempre lo ponía sin el signo
    Código: [Seleccionar]
    $ adelante y nunca me lo tomaba xD.
    En línea

    Desconectado k133

    • { L3 } Über
    • ***
    • Mensajes: 201
      • Ver Perfil
    Re:Dudas con IFS en Bash
    « Respuesta #3 en: Agosto 13, 2013, 03:12:43 pm »
    Si es eso es, en el for actuaría de esa manera. En el comando con el grep, según pone en el man (no me se todos los parámetros de memoria):
    Código: [Seleccionar]
           -p, --indicator-style=slash
                  append / indicator to directories

    Osea que te va a poner el '/' al final de los que son directorios, imagino que este lo usaras para seleccionar precisamente solo los directorios. Es una de las muchas formas que hay, no diría que la más acertada pero bueno.

    Pero como ya me "olía" como lo estabas haciendo, te invito a que leas el siguiente texto: http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29
    En línea
    Linux member #545609


    • Imprimir
    Páginas: [1]   Ir Arriba
    • Hack x Crack - Comunidad de Seguridad informática »
    • Programación »
    • Scripting »
    • Batch / Bash »
    • [SOLUCIONADO] Dudas con IFS en Bash
     

    • SMF | SMF © 2013, Simple Machines
    • XHTML
    • RSS
    • WAP2
    Va un mudo y le dice a un sordo: Hack x Crack usa cookies. Pues eso... Learn more