Bash Script,s


Índice:

         .- Test if a port on a remote system is reachable

         .- Obtener la IP externa

         .- Check for number of arguments

         .- Operadores

         .- Colorear salida

         .- Listar archivos recursivamente

         .- Reading a File Line By Line Syntax

         .- Recorrer todos los caracteres de una cadena

         .- Encuentra la posición de una subcadena en una cadena

         .- Obtener nombre del script sin ruta ni extensión

         .- Obtener nombre completo del script

         .- Obtener path del script

         .- Obtener path - nombre - extensión

         .- Leer una línea determinada de un archivo

         .- Crear un directorio

         .- Crear/obtener archivo de configuración de un script

         .- Mostrar ayuda

         .- String- Trim de una cadena

         .- String- Obtener posición subcadena en una cadena

         .- Preguntar Y/N

                if [[ $confirm =~ ^[Yy]$ ]]

         .- Command-Line Options and Switches

         .- Comprobar si un directorio es un punto de montaje

         .- Devolver valor desde una función

         .- Renombrar archivo de log cuando pasa de un tamaño dado

         .- Limpieza al salir del script

         .- Comprobar que el usuario es administrador

         .- Comprobar que el path termina en "/"; si no es así incluirla

         .- Incrementar una variable (contador/counter)

         .- Ejecutar un script al cerrar la sesión

         .- Asignar valor por defecto

         .- Redidigir salida /dev/null

         .- Añadir lineas a crontab

         .- Comprobar comandos requerimientos



.- Test if a port on a remote system is reachable  ⮴  

  xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22

  SSH-2.0-OpenSSH_6.2p2 Debian-6


.- Obtener la IP externa  ⮴  

  curl -4 ifconfig.co


.- Check for number of arguments  ⮴  

    EXPECTED_ARGS=1

    E_BADARGS=65

    if [ $# -gt $EXPECTED_ARGS ]

    then

      echo "Usage: ./extract [starting_directory]" >&2

      exit $E_BADARGS

    fi


    if [[ $# -ne 1 ]]; then

        echo "Illegal number of parameters"

        exit 2

    fi



.- Operadores  ⮴  

link=https://linuxhint.com/bash_operator_examples/



.- Colorear salida  ⮴  

link=https://www.devopsroles.com/bash-script-recursive-file-list/



.- Listar archivos recursivamente  ⮴  

    for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm $f; done

starkoverflow



.- Reading a File Line By Line Syntax  ⮴  

    while IFS= read -r line; do

      printf '%s\n' "$line"

    done < $input_file



.- Recorrer todos los caracteres de una cadena  ⮴  

    foo=$1

    for (( i=0; i<${#foo}; i++ )); do

      echo "${foo:$i:1}"

    done



.- Encuentra la posición de una subcadena en una cadena  ⮴  

    _strindex() { 

      x="${1%%$2*}"

      [[ "$x" = "$1" ]] && echo -1 || echo "${#x}"



    _strindex "$String" "$SubString"


.- Obtener nombre del script sin ruta ni extensión  ⮴  

# Directorio donde se guardarán todos los datos de configuración del script.

_cfg_name_only_script() {

  #local _name_script="$0"

  #local _name_script="${1:-$0}"

  local _name_script="${1:-${BASH_SOURCE[0]:-$0}}"

  local _name


  # --- Obtener nombre del script sin path, extensión ni punto inicial ---

  _name="${_name_script##*/}"   # quitar path

  _name="${_name%.*}"           # quitar extensión

  _name="${_name#.}"            # quitar punto inicial si existe


  echo "$_name"



Find the Script’s Filename


.- Obtener nombre completo del script  ⮴  

    echo "$(dirname $(readlink -f $0))/$0"


La solución anterior en el caso de tratarse de un enlace no se obtendría el

nombre del script, sino el del enlace.

Habría que usar esta solución:

    echo "$(dirname $(readlink -f $0))/$(basename "$(readlink -f "$0")")"




.- Obtener path del script  ⮴  

Cuatro posibilidades.

    echo `dirname $(realpath $0)`


    echo $(dirname $(readlink -f $0))

    echo $(dirname "$(readlink -f "$BASH_SOURCE")")


    pwd  <- No usar. Da el path actual

    $PWD <- No usar. Da el path actual


Path relativo:

    $(dirname "$0")


.- Obtener path - nombre - extensión  ⮴  

Dado el nombre completo de un archivo (fullfile) se puede obtener:

    fullfile="/home/juanp/Documentos/apuntes_portugues.odt"


..- El nombre del archivo:

      filename=$(basename -- "$fullfile")

filename=apuntes_portugues.odt


..- La extensión del archivo:

      extension="${filename##*.}"

extension=odt


..- El nombre del archivo sin la extensión:

      filename="${fullfile%.*}"

filename=/home/juanp/Documentos/apuntes_portugues


..- El nombre exclusivamente del archivo sin la extensión:

      filename=$(basename -- "$fullfile")

      filename="${filename%.*}"      

filename=apuntes_portugues.odt



..- Path del archivo:

      path=$(dirname "$fullfile")

path=/home/juanp/Documentos


.- Leer una línea determinada de un archivo  ⮴  

    # $1 Nombre completo del fichero

    # $2 Número de la linea a devolver

    function _read_file_line(){

      echo $(sed -n "$2{p;q}" "$1")



Más información



.- Crear un directorio  ⮴  


      #  Crea el directorio cuyo nombre se la pasa.


      #  Devuelve un código de error y se sale del script si se produce un error al

      #  crear el directorio (mkdir) o se le pasa una cadena vacia como nombre del 

      #  directorio a crea.


      create_folder(){


        l_folder=$1

        l_status=0


        # Comprobar si no se le ha pasado una cedena vacia

        if [ ! -z "$l_folder" ]; then

          # Si el diretorio no existiera ya se procede a crearlo

          if [[ ! -d "$l_folder" ]]; then

            mkdir "$l_folder"

            l_status=$?

            # Comprobar si se ha creado correctamente el directorio.

            # Si hubiera algún error, se muestra un aviso y se sale con el código de

            # error generado por mkdir

            if [[ "$l_status" -ne "0" ]]; then

              echo "Error function create_folder():"

              echo "Se ha producido un error al crear el directorio $l_folder"

              echo "Código de error de mkdir: $l_status"

              exit $l_status      

            fi

          fi

        else

          echo "Error function create_folder():"

          echo "No se ha pasado a la función el nombre del directorio a crear."

          exit 2

        fi




.- Crear/obtener archivo de configuración de un script  ⮴  


    #  Devuelve el nombre del archivo de configuración del script, si no existe 

    #  creará un archivo y devolverá su nombre.


    #  El archivo se creará en /home/.config/NAME_SCRIPT; se creará la extructura 

    #  de directorios (/.config) y (/NAME_SCRIPT) de ser necesario


    #  El nombre por defecto del archivo será NAME_SCRIPT_config.cfg; se puede

    #  elgir otro -sin path- y se le puede pasar a la función.


    #  Devuelve un código de error y se sale del script si se produce un error.


    create_config_file(){


      l_name=$1

      l_folder=""


      # Si no se le pasa el nombre será el del script.

      if [ -z "$l_name" ]; then

        l_name="$(dirname $(readlink -f $0))/$0"

        l_name=$(basename -- "$l_name")

        l_name="${l_name%.*}_config.cfg"      

      fi


      # Crear si no existe la carpeta /home/.config/$NAME_SCRIPT

      if [[ ! -d "$HOME/.config" ]]; then

        create_folder "$HOME/.config"    

      fi


      l_folder="$(dirname $(readlink -f $0))/$0"

      l_folder=$(basename -- "$l_folder")

      l_folder="${l_folder%.*}"

      if [[ ! -d "$HOME/.config/$l_folder" ]]; then

        create_folder "$HOME/.config/$l_folder"

        echo "" > "$l_folder/$l_name"    

      fi

      echo "$HOME/.config/$l_folder/$l_name"





.- Mostrar ayuda  ⮴  

Muestra las lineas del script contenidas entre las dos líneas #//# y elimina

el primer carácter de cada línea (#).


    if [[ ( $@ == "--help") ||  $@ == "-h" ]];then 

      s=0

      while read line; do

        if [ "$line" == "#//#" ]; then

          s=$((s+1))

        elif [ $s -eq 1 ]; then      

          echo "${line:1}"

        elif [ $s -gt 1 ]; then

          exit 0

        fi

      done < $0

    fi



.- String- Trim de una cadena  ⮴  


    echo "   lol  " | xargs


Fuente


    echo "=$(sed -e 's/^[ \t]*//' -e 's/\ *$//g'<<<"${output}")="

    ## more readable syntax  #

    echo "=$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'<<<"${output}")="

Fuente


.- String- Obtener posición subcadena en una cadena  ⮴  


    _strindex() { 

      x="${1%%$2*}"

      [[ "$x" = "$1" ]] && echo -1 || echo "${#x}"




Ejemplo


  str="hello world"

  substr="w"


  i=$(_strindex "$str" "$substr")

  if [ "$i" -eq -1 ]; then

    echo "nil"

  else

    echo ${str:$i:50}

  fi


La salida sería "world"





.- Preguntar Y/N  ⮴  

    read -p "Are you sure you want to continue? [y/N]: " confirm

    confirm=${confirm:-N}

    if [[ $confirm =~ ^[Yy]$ ]]  ⮴  

    else

      echo "Aborted by user."

      exit 1

    fi


    read -p "Please verify the checksum. Press 'y' to continue: " response

    if [[ ! $response =~ ^[Yy]$ ]]

    then

      echo "Aborting due to user response."

      exit 1

    fi




    while true; do

      read -p "¿Renombrar los archivos (Y/N) " yn

      case $yn in

        [Yy]* ) break;;

        [Nn]* ) echo 'Renombrado cancelado'; exit;;

        * ) echo "La respuesta ha de ser yes o no.";;

      esac

    done


Otra forma:



    # Realiza una pregunta y espera respuesta Yes or No


    # Devuelte:

    # 0 -> Yes

    # 1 -> No


    # 1 -> Pregunta

    # 2 -> Msj previo [Opcional]


    # Forma de uso:


    #  _yes_no "pregunta" "pre pregunta"

    #  if [ $? -eq 0 ];then

    #    echo "yes"

    #  else

    #    echo "no"

    #  fi




    function _yes_no(){


      local l_r=1


      while true; do

        echo "" 

        if [ ! -z "$2" ]; then

          echo $2

        fi

        read -p "$1 (Y/N) " yn

        case $yn in

          [Yy]* ) l_r=0;break;;

          [Nn]* ) l_r=1;break;;

          * ) echo "La respuesta ha de ser yes o no.";;

        esac

      done 


      return $l_r  








.- Command-Line Options and Switches  ⮴  

Command-Line Options and Switches



.- Comprobar si un directorio es un punto de montaje  ⮴  

  if [ "$(grep "$Directorio " /proc/self/mountinfo)" != "" ]; then

    echo 1

  else

    echo 0

  fi


"$Directorio " -> con el espacio al final


ver man mountpoint



.- Devolver valor desde una función  ⮴  


1) Asignar el resultado a una variable global:


      function myfunc()


          myresult='some value'



      myfunc

      echo $myresult    



2) Utilizar la sustitución de comandos:


      function myfunc()


          local  myresult='some value'

          echo "$myresult"



      result=$(myfunc)   

      echo $result



3) Escribir la función de forma que acepte un nombre de variable como parte de

su línea de comandos y, a continuación, establecer esa variable en el re-

sultado de la función:


      function myfunc()


          local  __resultvar=$1

          local  myresult='some value'

          eval $__resultvar="'$myresult'"



      myfunc result

      echo $result    


El la variable pasada en la línea de comandos y el de la variable local que

almacena su valor deben ser diferentes, en caso contrario no funcionará.

El siguiente ejemplo no funcionará:


      # ¡ No funciona !


      function myfunc()


          local  result=$1

          local  myresult='some value'

          eval $result="'$myresult'"



      myfunc result

      echo $result



4) Usar return


Aunque bash tiene una sentencia return, lo único que se puede especificar

con ella es el estado de la función, que es un valor numérico como el valor

especificado en una sentencia exit. El valor de estado se almacena en la va-

riable $?. Si una función no contiene una sentencia return, su estado se es-

tablece basándose en el estado de la última sentencia ejecutada en la fun-

ción.


      _yes_no(){


        local l_r=1


        while true; do

          read -p "$1 (Y/N) " yn

          case $yn in

            [Yy]* ) l_r=0;break;;

            [Nn]* ) l_r=1;break;;

            * ) echo "La respuesta ha de ser yes o no.";;

          esac

        done 


        return $l_r  



      _yes_no "pregunta"

      if [ $? -eq 0 ];then

        echo "yes"

      else

        echo "no"

      fi



Fuente



.- Renombrar archivo de log cuando pasa de un tamaño dado  ⮴  

    #!/bin/bash



    #  Renombar archivo de log



    #  Renombra el archivo que se le pasa si supera el tamaño indicado.


    #  Ejemplo:


    #   _check_size_log "fichero.txt"  100000


    #     Si el tamaño del archivo supera los 100000 renombrará el archivo 

    #     incluyendo un valor numérico consecutivo.


    #       fichero_1.txt, fichero_2.txt, ... fichero_n.txt


    # Versión: 1.00

    # Fecha  : 24/12/22




    function _get_size(){

      echo "$(find "$1" -printf "%s")"



    function _rename_log(){


      local l_name_log="$1"

      local l_i=1


      while [ $l_i -le 100000 ]; do

        if [[ ! -e "${l_name_log%.*}_$l_i.${l_name_log##*.}" ]]; then

          mv $l_name_log "${l_name_log%.*}_$l_i.${l_name_log##*.}"

          break

        fi

        l_i=$(( $l_i + 1 ))

      done



    function _check_size_log(){


      local l_name_log="$1"

      local l_limite_size="$2"

      local l_size=0


      l_size=$(_get_size $l_name_log)


      if [[ $l_size -gt $l_limite_size ]]; then

        _rename_log "$l_name_log"

      fi




    _check_size_log "$1" "$2"



.- Limpieza al salir del script  ⮴  

    function _trap_exit(){

      # Capturar el estado de salida. Si es 0 no hay error.

      l_error=$?


      ... tareas a realizar antes de salir del script

          en este caso elimianr ...


      rm -f "$f_mounts"

      rm -f "$f_points"

      rm -f "$f_result"



    trap _trap_exit EXIT


    f_mounts=$(mktemp)

    f_points=$(mktemp)

    f_result=$(mktemp)


En la línea " trap _trap_exit EXIT " se estable la función que se llamará al

salir del script, debe estar definida antes.



.- Comprobar que el usuario es administrador  ⮴  

    [[ ${EUID} -ne 0 ]] && {

    printf "Debe ejecutar el script como root. Intente 'sudo $0'\n"

    exit 1




.- Comprobar que el path termina en "/"; si no es así incluirla  ⮴  

    if [[ ! "${l_path:${#l_path}-1}" == "/" ]]; then

      l_path="$l_path""/"

    fi


.- Incrementar una variable (contador/counter)  ⮴  

  i=$((i+1))

  ((i=i+1))

  let "i=i+1"


  i=$((i-1))

  ((i=i-1))

  let "i=i-1"


  ((i+=1))

  let "i+=1" 


  ((i-=1))

  let "i-=1" 


Fuente - linuxize



.- Ejecutar un script al cerrar la sesión  ⮴  

Habría que inculir el siguiente código en un archivo que depende del login

manager que se esté usando.

  if [ ${USERNAME} = "myuser" ];then

    su myuser -c /home/myuser/logout.sh

  fi


En Gnome el archivo es /etc/gdm3/PostSession/Default


No obstante, esto funciona exclusivamente al cerrar la sesión, no cuando el

usuario apaga el equipo.


Fuentes:

Fuente 1

Fuente 2



.- Asignar valor por defecto  ⮴  

    function write_ctrl_seconds_find() {

      local l_file="$1"

      l_file="${l_file:="/home/myhome/mifichero.txt"}"    



.- Redidigir salida /dev/null  ⮴  

El "archivo" /dev/null es un “cubo de basura” al que se puede redidigir la sali-

da de un comando.


Los valores estándar son:

.- entrada     STDIN    0

.- salida      STDOUT   1

.- error       STDERR   2


Redirigir los mensajes de error:

    usuario@laptop:~$ cat pruebas 2>/dev/null


Redirigir los mensajes de error a un archivo de log:

    usuario@laptop:~$ cat pruebas 2 >err.log


Redirigir la salida:

    usuario@laptop:~$ cat pruebas 1>/dev/null


Redirigir la salida y los mensajes de error:

    usuario@laptop:~$ cat pruebas > /dev/null 2>&1



.- Añadir lineas a crontab  ⮴  

  echo "Incluyendo en croontab la tarea de sincronizacion"

  (crontab -l; echo "@reboot bash $HOME/script/manto/t_sync_nextcloud.sh";) | awk '!x[$0]++'  | crontab -

  if [ ! $? -eq 0 ];then

    _error "Al incluir linea en crontab"

  else

  _fin_copia

  fi



.- Comprobar comandos requerimientos  ⮴  

  # Check for required commands

  REQUIRED_COMMANDS=("rsync" "parted" "wipefs" "mkfs.vfat" "mkfs.ntfs" "udisksctl" "sha256sum" "mount" "umount" "mkdir" "cp" "sync" "mktemp")


  echo "Checking for required commands..."

  for cmd in "${REQUIRED_COMMANDS[@]}"; do

      if ! command -v $cmd >/dev/null 2>&1; then

          echo "Missing command $cmd. Please install the corresponding package and rerun this script."

          exit 1

      fi

  done

  echo "All required commands are available."