Archivo de Etiquetas de 'bash'

Obtener las extensiones de fichero existentes en un directorio

Una mini-receta rápida para obtener, de forma recursiva, todas las extensiones de fichero que existan a partir de un directorio dado:

find directorio_raiz -type f -exec sh -c 'basename $0 | sed "s/.*\.//"' {} \; | sort | uniq

El truco viene del archipoderoso sed, que permite obtener las extensión de un fichero mediante la orden sed “s/.*\.//”, y funciona que yo sepa, para cualquier Unix con una shell compatible con sh y find, basename y sed instalados.

Programmed shutdown: pequeño script para apagar la máquina

Programmed shutdown: step 1

Paso 1: ¿cuánto tiempo?

Después de buscar (no, mucho, eso si :D ) por Google y no encontrar algo que se adaptase a mis mínimas necesidades, me he hecho un pequeño script de apagado de la máquina para mi maravilloso PC en el salón (que no de salón :) ) equipado con un GNU/Linux (en concreto una Debian, pero el script es multiversal dentro del mundo Linux :-P y quizá Unix, depende de si el software zenity está en otras plataformas o no).

Programmed shutdown: step 2

Paso 2: tú tranqui, que ya te aviso yo...

La idea es poder pedirle a la máquina que se apague dentro de equis minutos, con posilibidad de cancelarlo y cierto feedback visual de cuánto tiempo te queda. Posibles usos son por ejemplo imitar la función Sleep de algunas televisiones, o, cuando te vas de vacaciones y tienes algunas descargas tirando, o algún programa de TV que quieres que se grabe, pedirle que se apague en unos días para no consumir energía tontamente.

El script sólo requiere que esté instalado Zenity. El código fuente del mismo lo podéis ver a continuación:

#!/bin/bash
# Ask for time in minutes to sleep and ater that poweroff the computer
# needs - zenity
# Diego Toharia - deigote@deigote.com

# Messages
TITLE="Apagar el ordenador"
MINUTES_QUESTION="¿Dentro de cuántos minutos?"
WAIT_PRE="Esperando"
WAIT_POST="minutos"

minutes=`zenity --entry --title "$TITLE" --text "$MINUTES_QUESTION" 2>&1` || exit
seconds=`expr $minutes "*" 60`

if [ $seconds != "" ] ; then
	for i in `seq 1 $seconds` ; do
		percentage=`expr $i "*" 100`
		percentage=`expr $percentage "/" $seconds`
		echo $percentage
		sleep 1
	done | zenity --title="$TITLE" --text="$WAIT_PRE $minutes $WAIT_POST" --progress --auto-close --auto-kill
	poweroff
fi

También quiero pensar que, si alguna vez cambio algo, podréis encontrar una versión actualizada en el enlace Programmed shutdown script pero no garantizo que cumpla mis propósitos :-D .

Programmed shutdown: laucher

Programmed shutdown: laucher

Para invocarlo, basta guardarlo en un directorio que esté en el path (yo suelo usar para estos scripts $HOME/bin) y darle permisos de ejecución. Recordar que debéis tener permisos para ejecutar el mandato poweoff. En mi caso, tengo en la barra inferior un lanzador precedido del mandato gksudo, de tal manera que el script se lanza con los permisos necesarios, pidiéndome la contraseña en caso necesario.

Si la salida fuese un Excell, lo llamaríamos ingeniería del software

Lo que ha empezado como un simple conteo de ficheros para ver qué proyecto hacía que Eclipse fuese lento, ha terminado en todo un contador de líneas digno de aparecer en cualquier libro de ingeniería del software (nótese la cursiva, por favor :???: ), si no fuera porque es un script de consola bash con salida de texto simple.

Al grano:

#!/bin/bash
EXTENSIONES="$@"
ficheros_total=0
lineas_total=0
vacias_total=0
novacias_total=0
for ext in $EXTENSIONES ; do
   echo EXTENSION $ext
   ficheros=`find . -name "*.$ext" | wc -l`
   lineas=`find . -name "*.$ext" | xargs cat | wc -l`
   novacias=`find . -name "*.$ext" | xargs cat | awk 'BEGIN { lineas = 0 } { if ($0 != "") lineas++} END { print lineas }'`
   vacias=`find . -name "*.$ext" | xargs cat | awk 'BEGIN { lineas = 0 } { if ($0 == "") lineas++} END { print lineas }'`
   porcentaje=`echo $vacias $lineas | awk '{ print $1 / $2 * 100 }'`
   echo Tiene $ficheros ficheros de tipo $ext y $lineas lineas, de las cuales $novacias tienen contenido y $vacias son vacias \(un $porcentaje %\)
   ficheros_total=`expr $ficheros_total + $ficheros`
   lineas_total=`expr $lineas_total + $lineas`
   vacias_total=`expr $vacias_total + $vacias`
   novacias_total=`expr $novacias_total + $novacias`
done
if [[ $# -gt 1 ]] ; then
   porcentaje_total=`echo $vacias_total $lineas_total | awk '{ print $1 / $2 * 100 }'`
   echo TOTAL
   echo Tiene $ficheros_total ficheros en total, con $lineas_total lineas, de las cuales $novacias_total tienen contenido y $vacias_total son vacias \(un $porcentaje_total %\)
fi

Ejemplo de uso (guardandolo en un fichero cuenta_lineas.sh accesible por el path y con los permisos adecuados):

$ cd directorio_raiz_del_proyecto/ ; ./cuenta_lineas.sh java jsp xml
EXTENSION java
Tiene 388 ficheros de tipo java y 60035 lineas, de las cuales 47806 tienen contenido y 12230 son vacias (un 20.3714 %)
EXTENSION jsp
Tiene 792 ficheros de tipo jsp y 91354 lineas, de las cuales 75267 tienen contenido y 16088 son vacias (un 17.6106 %)
EXTENSION xml
Tiene 170 ficheros de tipo xml y 32282 lineas, de las cuales 30437 tienen contenido y 1846 son vacias (un 5.71836 %)
TOTAL
Tiene 1350 ficheros en total, con 183671 lineas, de las cuales 153510 tienen contenido y 30164 son vacias (un 16.4228 %)

Mola :mrgreen: aunque es mejorable sacando porcentajes (ver abajo :-D ), pero no he encontrado un mandato tipo expr que trabaje con floats :neutral: (a ver si algún comentarista me da el tip :-) )

EDITO: Ya se me ha ocurrido cómo hacer los porcentajes mientras contestaba :lol: actualizado el código y la salida del mismo

EDITO de nuevo: Si queréis añadir más filtros a las lineas vacías, tal y como sugiere Kortatu (que yo ya he barajado), tendréis que cambiar la línea

novacias=`find . -name "*.$ext" | xargs cat | awk 'BEGIN { lineas = 0 } { if ($0 != "") lineas++} END { print lineas }'`

por

novacias=`find . -name "*.$ext" | xargs cat | grep -v '^$' | grep -v '^\s*\}\s*$'  | grep -v '^\s*\*.**$' | grep -v '^\s*/\*\*.*$' | grep -v '^\s.//.*$'

Útil para código de la familia Java :D. ¡Gracias!

Bucles en la terminal

Hace poco necesitaba yo borrar, en una estructura de directorios, todos los ficheros cuya extensión fuera .class. Estas tareas suelen ser un tedio, pero muy fáciles de solucionar si sabes un poco de shell scripting. El ejemplo es el siguiente:

$ for i in `find . -name '*.class'` ; do echo "Borrando $i" ; rm "$i" ; done
Esto haría la magia en una terminal con intérprete de mandatos bash. Si usais tcsh como yo, la cosa es un poco distinta:

$ foreach i ( ` find . -name '*.class' ` )
foreach? echo "Borrando $i"
foreach? rm $i
foreach?end

Como se ve, en tcsh es un poco menos intuitivo, ya se sabe que para programar, bash es bastante mejor :-), pero el resultado es equivalente.