Saltar a contenido

Recetas Bash

Configuración

  • Configuración de los locales para que funcione todo bien: export LANG=es_ES.UTF-8
  • Listar con colorines: ls -h --color. Para que salga por defecto, se añade un alias en el .bashrc: alias ls='ls -h --color'
  • Mantener el histórico de comandos entre sesiones: añadir shopt -s histappenden el .bahsrc

Genérico

Ignorar mayúsculas o minúsculas en un for en Bash

shopt -s nocaseglob

Emular el comando tree de dos

ls -R | grep : | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /'  -e 's/-/|/'

Copia recursiva de ciertos ficheros

cp -R --copy-contents *.jpg origen/ destino

Sistema

Generar número aleatorio

# Devuelve un número aleatorio entre 1 y 100
echo $[ ( $RANDOM % 100 ) + 1 ]

Monitoriza la memoria libre

#!/bin/bash
while [ true ] ; # se estará ejecutando indefinidamente
do
    mem=`free -m |awk 'NR==2 {print $4}'`

    # free -> da la memoria libre del sistema
    #     -m : en megas
    # awk -> extrae texto
    #     NR==2 : la 2ª línea
    #     {print $4}: la 4ª columna

    if [ $mem -lt 10 ]; # Cuando sea menor de 10
    then
        echo "La memoria libre es menor de 10MB" | /bin/mail -s "ERROR MEMORIA" sarita@correo.com
    fi        
sleep 5 # Esperamos 5 segundos, antes de la siguiente ejecución del bucle
done # fin while

Informe diario de los servidores OAS

#!/bin/bash
# /root/test_oas
################################################
# #Comprueba el estado de los servidores OAS y #
# # envia correo con la información            #
# #                                            #
# # Notas:                                     #
# #                                            #
# # - Se ejecuta todas los noches via crontab  #
# #                                            #
# # Versiones:                                 #
# #                                            #
# # - 1/4/04: Creacióscript (R.Hernando)       #
# # - 12/10/04: modif (RFS y JGVF)             #
# # - version 2 (30/05/07):                    #
# #   solo envia el correo en caso de errores  #
# ##############################################

# -----------------------
# Variables
# -----------------------
FICHERO=/root/estado_oas.tmp
FECHA=`date +"%d%h%y"`
SERVIDOR=`hostname -s`
CORREO="0" #Flag para enviar el correo (si permanece como 0 no se envia, si ocurre algun error se modifica a 1 y se envia el correo)

# ----------------
# Servidor PreExplotacion10g
# ----------------

echo '=================================================' >> $FICHERO
echo 'ULTIMA COMPROBACION DE SERVIDOR PREEXPLOTACION10g' >> $FICHERO
echo '=================================================' >> $FICHERO


# Comprueba los logs de mas de 500MB

echo 'Ficheros de mas 500 MB: ' >> $FICHERO
echo '-------------------------- ' >> $FICHERO

find / -type f \( -size +500000k \) -exec ls -lh {} \; | grep -v "/backup" | grep -v "/proc" | awk '{print $9 " --> " $5 "\n"}' >> $FICHERO
tail -2 $FICHERO | grep "\-\->" 
if [ $? = 0 ] # Existe algun fichero de mas de 500 MB
then 
  CORREO=1 
else
  echo "No hay ninguna" >> $FICHERO
fi

# Comprueba el estado de las instancias
echo >> $FICHERO
echo 'Estado de las instancias: ' >> $FICHERO
echo '------------------------- ' >> $FICHERO

su - ias10g -c 'opmnctl status | grep -v dcm-daemon | grep -v home | grep -v logloaderd | grep -E "Init|Stop|Down"' >> $FICHERO
if [ $? = 0 ] #Existe alguna instancia chunga
then
  CORREO=1
else
  echo "todas arriba" >> $FICHERO
fi

# Comprueba el espacio libre en el sistema de ficheros
echo >> $FICHERO
echo 'ULTIMA COMPROBACION DEL Espacio disponible en el Sistema de Ficheros: ' >> $FICHERO
echo '--------------------------------------------- ' >> $FICHERO
echo -e 'Particion \t Disponible' >> $FICHERO
PARTICIONES=`df -h | awk '{print $5}' |grep -v Us|cut -d'%' -f1`
for i in $PARTICIONES
do
  if [ $i -ge 90 ] #Alguna particion ocupa mas del 90%
  then
    CORREO=1
  fi
done
df -h | awk '{print $6 "\t\t" $5 "\t" $4}' | grep -v '/dev/shm' | grep -v 'Mounted' >> $FICHERO

# ------------
# Envia correo
# ------------


#mail -s "Estado OAS10g $SErVIDOR el $FECHA" sa-sic@jcyl.es < $FICHERO
if [ "$CORREO" = "1" ]
then
 mail -s "ERRORES en $SERVIDOR el $FECHA" sa-sic@jcyl.es < $FICHERO
else
  mail -s "$SERVIDOR OK el $FECHA" sa-sic@jcyl.es < /dev/null
fi
#vaciamos $FICHERO
 > $FICHERO

Ficheros

Quitar líneas repetidas en un fichero

cat fichero | uniq 

Previamente el fichero ha de estar ordenado.

Nota: con sort -u ordenamos y quitamos las líneas repetidas.

Generar web a partir de markdown

#!/bin/bash
# Genera una estructura html a partir de ficheros md (markdown)
# 1. Genera la estructura de directorios
# 2. Construye los html
# 3. Genera un fichero índice con un enlace a todos los documentos

OUTPUT=HTML

if [ ! -d $OUTPUT ];
then
    mkdir $OUTPUT
fi    

files=($(find ./ -type f -name '*.md'))
for i in ${files[*]}
do
  printf " Procesando %s..." "${i}" 
  if [ ! -d "$OUTPUT/$(dirname ${i})" ];
  then
        mkdir "$OUTPUT/$(dirname ${i})"
        printf ".."
  fi
  pandoc -s -S -t html "${i}" -o "${OUTPUT}/$(dirname ${i})/$(basename ${i%.md}.html)"
  printf "... ok\n"  
done

Corrige el nombre de los ficheros Unix para que no den problemas si se copian en sistemas de ficheros Windows

rename -v 's/[^\x00-\x7F]|\?|\://g' *

Cambiar extensión de un grupo de ficheros

Se cambian todos los ficheros con extensión .MOD de un directorio a extensión .mpeg:

for i in *.MOD; do mv "$i" "${i[@]/%MOD/mpeg}"; done

Se hace lo mismo, pero recursivamente en los subdirectorios:

for i in `ls -r */*.MOD`; do mv -v "$i" "${i[@]/%MOD/mpeg}"; done

Multimedia

Renombrar ficheros según las etiquetas mp3

Para renombrar un fichero:

#!/bin/bash
# Renombra el fichero según las etiquetas mp3, de la forma: NºCanción-Título
TITLE="`id3info "$1" | grep '^=== TIT2' | sed -e 's/.*: //g'`"
#ARTIST="`id3info "$1" | grep '^=== TPE1' | sed -e 's/.*: //g'`"
#ALBUM="`id3info "$1" | grep '^=== TALB' | sed -e 's/.*: //g'`"
#YEAR="`id3info "$1" | grep '^=== TYER' | sed -e 's/.*: //g'`"
TRACKNUM="`id3info "$1" | grep '=== TRCK'| sed -e 's/.*: //g' | cut -d / -f 1`"

#echo "$TRACKNUM - $TITLE.mp3"

mv $1 "$TRACKNUM - $TITLE.mp3" 

Para renombrar varios ficheros se llama a este script de la forma

for i in *mp3; do renameMp3.sh $i; done

Convierte un disco en ape y cue en los flac correspondientes

# Convertir el ape en flac
ffmpeg -i audio.ape audio.flac
rm audio.ape
# Si tiene un fichero cue dividirlo en pistas:
cuebreakpoints audio.cue | shnsplit -o flac audio.flac -f audio.cue -t "%n - %t"
rm audio.cue
# Etiquetar las pistas
metaflac --export-tags-to=tag.txt audio.flac
rm audio.flac
metaflac --remove-all *.flac
metaflac --import-tags-from=tag.txt *.flac
rm tag.txt
# Añadir carátula
metaflac --import-picture-from=folder.jpg *.flac
# Cambiar el título y el número de pista
metaflac --remove-tag=Title *.flac
for file in *.flac; do titulo=`expr "$file" : '[0-9][0-9] - \(.*\)\.flac$'`; track=`expr "$file" : '^\([0-9][0-9]\) - .*\.flac'`; metaflac --set-tag="Title=$titulo" "$file"; metaflac --set-tag="TrackNumber=$track" "$file"; done 

Convierte todos los .flac del directorio actual en .mp3

# /opt/bin/flac2mp3.sh
for file in *.flac; do
    # Extension
    OUTF="${file[@]/%flac/mp3}"
    # Si no existe la carátula se extrae
    if [ ! -f folder.jpg ]; then
        metaflac --export-picture-to=folder.jpg "$file"
    fi
    # Se extraen las etiquetas
    ARTIST=$(metaflac "$file" --show-tag=ARTIST | sed s/.*=//g)
    TITLE=$(metaflac "$file" --show-tag=TITLE | sed s/.*=//g)
    ALBUM=$(metaflac "$file" --show-tag=ALBUM | sed s/.*=//g)
    GENRE=$(metaflac "$file" --show-tag=GENRE | sed s/.*=//g)
    TRACKNUMBER=$(metaflac "$file" --show-tag=TRACKNUMBER | sed s/.*=//g)
    DATE=$(metaflac "$file" --show-tag=DATE | sed s/.*=//g)
    COMMENT=$(metaflac "$file" --show-tag=COMMENT | sed s/.*=//g)
    # Se convierte a mp3 con las etiquetas y la carátula
    flac -c -d -s "$file" | lame -h -b 320 --add-id3v2 --pad-id3v2 --ignore-tag-errors \
        --ta "$ARTIST" --tt "$TITLE" --tl "$ALBUM"  --tg "${GENRE:-12}" \
        --tn "${TRACKNUMBER:-0}" --ty "$DATE" --tc "$COMMENT" --ti "folder.jpg" - "$OUTF"
done
# Mover los mp3 a un directorio
mkdir mp3
mv *.mp3 mp3/

Convertir un pdf en varias imágenes

Necesita imagemagic y ghostscript.

Genera una imagen con cada página del pdf

convert -density 300 musica.pdf musica.png

Convertir todos los png a svg

for i in *.png; do convert "$i" "${i[@]/%png/svg}" ; done

Reescala imágenes

En este caso carátulas de calibre

#!/bin/bash
# Reescala las carátulas de calibre para que no ocupen tanto
# .. Debe existir el fichero resize.txt (se utiliza como
# .. flag para no reescalar continuamente las mismas carátulas
# .. (estropeándolas poco a poco)
while read file
do
      nconvert -quiet -ratio -resize 680 680 -rflag decr -q 60 -overwrite "$file"
done < <(find . -newer resize.txt -name \cover.jpg)
touch resize.txt

Reducir imagen

Reducir tamaño de una imagen con buena calidad (por ejemplo para generar un pdf)

convert -resize 60% -filter Lanczos -density 150 -quality 100 esb_original.png esb.png

Automatización

Crea un correo a partir de la plantilla correspondiente

#!/usr/bin/bash
# correo.sh
# ....Crea un nuevo mensaje de correo
# ....a partir de una de las plantillas de outlook
#
# ....Uso: correo.sh <tipo>
# ....Los distintos tipos son:
# ....       * deploy       : a SGF2-DES      voy a desplegar en desarrollo
# ....       * deployOK     : a SGF2-DES      he desplegado en desarrollo
# ....       * preFC        : a FC            hay una nueva versión en preexplotación
# ....       * expFC        : a FC            hay una nueva versión en explotación
# ....       * preFPO       : a FPO           hay una nueva versión en preexplotación
# ....       * expFPO       : a FPO           hay una nueva versión en explotación
# ....       * preFIP       : a FIP           hay una nueva versión en preexplotación
# ....       * exp          : a jefes         hay una nueva versión en explotación
# ....       * ausencia     : a todos         vacaciones, moscosos, cursos y demás

# Variables
DIR_PLANTILLAS="C:\Users\hervelro\AppData\Roaming\Microsoft\Plantillas"

case $1 in
    deploy)   PLANTILLA="Voy a desplegar en desarrollo.oft";;
    deployOK) PLANTILLA="hecho despliegue en des.oft";;
    preFC)    PLANTILLA="SGF2_FC - Pase a preexplotación.oft";;
    expFC)    PLANTILLA="SGF2_FC - Pase a explotación.oft";;
    preFPO)   PLANTILLA="SGF2_FPO - Pase a preexplotación.oft";;
    expFPO)   PLANTILLA="SGF2_FPO - Pase a explotación.oft";;
    preFIP)   PLANTILLA="SGF2_FIP - Pase a preexplotación.oft";;
    exp)      PLANTILLA="SGF2 - Nueva versión en explotación.oft";;
    ausencia) PLANTILLA="SGF2 - Ausencia.oft";;
    *)        echo "Opción incorrecta.  
Las posibles opciones son: 
              deploy, 
              deployOK, 
              preFC, 
              preFPO, 
              preFIP, 
              exp, 
              ausencia";
              exit 1;;
esac        

start "" "${DIR_PLANTILLAS}"/"${PLANTILLA}"
exit 0

Copia un fichero al NAS desde el trabajo a través del proxy, con scp

# C:\cmder\bin\cpnas.sh
# Copia de un fichero dado al synology desde el trabajo vía el proxy ntlm
# Por defecto lo copia a /tmp

# Nota: la conexión tiene que ser con el usuario admin, ya que usuarios con menos privilegios
#no tienen habilitado Tcp Forwarding en sesiones SSH

# Nota2: parece que desde la junta han cortado la conexión a ritos.ddns.jazztel.es. 
# Así que ahora lo hago con un ping, para que se conecte a la ip en lugar de al nombre.

ip_ritos=$(ping -n 1 ritos.ddns.jazztel.es| grep -m 1 -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')

# Explicación del grep
# -m 1          -> solo la primera aparición
# -oE           -> la palabra que cumple la expresión regular
#([0-9]{1,3}\.){3}[0-9]{1,3} -> xxx.xxx.xxx.xxx donde cada xxx puede ser de 1 a 3 dígitos

if [[ $1 == "-h" ]]
then
    printf "%b" "cpnas [-r] Fichero-a-copiar [Destino]\n"
    printf "%b" "\t-r: Copia remota\n"
    printf "%b" "\tPor defecto el Destino en copia normal es /tmp y en copia remota el directorio actual\n"
    exit 0
fi 

if [[ $1 == "-r" ]]
then
    REVERSO=1
    ORIGEN=$2
    if [[ -n "$3" ]]
    then
        DESTINO=$3
    else
        DESTINO="."
    fi
else
    REVERSO=0
    ORIGEN=$1
    if [[ -n "$2" ]]
    then
        DESTINO=$2
    else
        DESTINO="/tmp"
    fi
fi

printf "%b" "\nSe va copiar "
if (( REVERSO == 1 ))
then
    printf "%b" "desde "
else
    printf "%b" "al "
fi    
printf "%b" "NAS el fichero $ORIGEN a $DESTINO\n"
printf "%b" "\n"
printf "%b" "\n\nContinuar?\n"
select respuesta in Si No
do
    if [ "$respuesta" == "No" ]
    then
        printf "%b" "\nHasta otra\n"
        exit 0
    elif [ "$respuesta" == "Si" ]
    then
        if (( REVERSO == 1 ))
        then
            scp -r -o "ProxyCommand connect -H localhost:5865 %h %p" -P 443 admin@$ip_ritos:"$ORIGEN" "$DESTINO"
        else
            scp -o "ProxyCommand connect -H localhost:5865 %h %p" -P 443 "$ORIGEN" admin@$ip_ritos:"$DESTINO"
        fi        
        exit 0
    fi
done



# -o "ProxyCommand connect -H localhost:5865 %h %p" -> se conecta utilizando el proxy habilitado en localhost:5865 (proxy ntlm)
# -P 443                        -> se conecta al puerto 443 (redirigido por el router al 2222 del nas
# admin@ritos.ddns.jazztel.es   -> usuario admin
# $*    -> se pasan todos los parámetros, usualmente será el nombre del fichero. También se puede
#          pasar -r para que la copia sea del nas al ordenador

Copia de seguridad de la Wiki

wget -m ftp://rhernand:*******@ftp.cluster010.hosting.ovh.net/wiki/* -P /volume2/backup/wiki
tar -zcvf /volume2/backup/wiki/backup-$(date +%Y-%m-%d-%H-%M-%S).tar.gz /volume2/backup/wiki/ftp.cluster010.hosting.ovh.net/

Conversión dng a jpg

#/opt/dng2jpg.sh
# Convierte todos los ficheros dng de un directorio a jpg (con imagemagic)
for file in *.dng; do
    OUT="${file[@]/%dng/jpg}"
    echo "Convirtiendo '$file' en '$OUT'"
    convert "$file" "$OUT"
done

Actualiza Web

# /opt/bin/actualizaWeb.sh
# Compila la nueva web
# hugo update ...
cd /var/services/homes/roberto/Drive/Aplicaciones/web
/opt/bin/hugo -v -d /volume2/www > /tmp/hugo.log
# Actualiza la web vía ftp
lftp -u rhernand,******* -d -e "mirror -vneR --ignore-time /volume2/www /www" ftp.cluster010.hosting.ovh.net > /tmp/ftp.log

Borrar los ficheros de log de más de 1 día de duración

#!/bin/bash
echo "Cleaning logs over $1 days old"
find /log_dir -ctime "$1" -name '*log' -exec rm {} \;

Borra líneas de un fichero, mediante sed

En este ejemplo las líneas 1 a 10

sed -n -e :a -e '1,10!{P;N;D;};N;ba'

Búsqueda

Busca todas las cadenas de caracteres que puedan coincidir con una dirección IP

grep -m 1 -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'

Buscar clases java dentro de jars

Cómo buscar clases dentro de un directorio con jar:

find . -name "*.jar" |xargs grep -il NombreClase

Buscar cadena de texto en todos los ficheros

find -type f -exec grep -l "jcyl_sanidad_proxy" {} +

y si queremos que la búsqueda sea exacta (por palabras)

find -type f -exec grep -lw "jcyl_sanidad_proxy" {} +

awk

Cambiar delimitador de un fichero

Tenemos un csv generado con Excel, delimitado por comas:

None

Con

awk '{$1=$1}1' FS="," OFS="\t" file4.csv > file4.txt

pasaríamos a tener:

None

  • {$1=$1}1: Reinicia el buffer
  • FS="," : Se le dice a awk que el delimitador actual es ,
  • OFS="\t" : Se le dice a awk que el nuevo delimitador pasa a ser \t

Convertir columnas en filas

Se tiene el fichero:

None

haciendo

awk '{for(i=1;i<=NF;i++){print $i}}' file5.txt > file5_new.txt

se tiene:

None

Convertir filas columnas en columnas

Partiendo del fichero anterior, si hacemos

​cat file5_new.txt | tr '\n' ' ' | awk '{$1=$1}1' FS=" " OFS="\t" > file5_restore.txt

Obtener suma de una columna

Tenemos el fichero

None

Si se quiere la suma de la columna col3:

awk 'BEGIN{FS="\t";count=0}{if(NR>1){count+=$3}}END{print count}' file6.txt

se obtiene: 171


Última actualización: March 4, 2022