Linux

Trucos Desde La Terminal

ALGUNOS TIPS PARA HACER COSAS MUY ÚTILES

Estos programas, scripts y comandos han sido probados en distribuciones Ubuntu/Debian de Linux. Siéntanse libres de contactarme a fgonzalez[at]lpmd.cl

MANIPULANDO ARCHIVOS DE TEXTO/DATOS

MANIPULANDO FOTOS/VIDEOS/PDF

INTERNET

SISTEMA OPERATIVO

GNUPLOT


MANIPULANDO ARCHIVOS DE TEXTO/DATOS

28 de Julio, 2021

ENCONTRAR ARCHIVOS

  • Para buscar un archivo por su nombre, desde el directorio actual (.), usamos
 find . -iname "archivo"
La opción -iname ignora diferencias entre mayúsculas y minúsculas.
  • Podemos buscar por extensión, por ejemplo, todos los archivos .pdf:
find . -iname "*.pdf"
  • Podemos buscar archivos en Linux o MacOS y buscar palabras dentro de ellos. Por ejemplo, para buscar todos los archivos .cc en la carpeta Programas/, y buscar en ellos la palabra cmath, ejecutamos
find Programas/ -iname "*.cc" -exec grep "cmath" {} +
  • Para encontrar sólo archivos (excluir directorios) que fueron modificados por última vez en Diciembre en el directorio "~/examples"
find ~/examples/ -type f -exec ls -ltr {} + | grep "Dec"

Si tu sistema operativo está instalado en inglés, cambia "Dec" por "Dic".

  • Podemos usar find para comprobar que cada uno de los archivos de cierto directorio es idéntico a uno, con el mismo nombre, en otro directorio:
find directory1/ -type f -exec diff -q  {} directory2/{}  \;
  • Con excepciones (por ejemplo, no considerar los archivos .dat):
find directory1/ -type f -not -name "*.dat" -exec diff -q  {} directory2/{}  \;
  • Encontrar todos los archivos que han sido modificados en los ultimos 30 dias:
find . -type f  -mtime -30d -exec ls -ltr {} +

Al ocupar -exec dentro de find, el símbolo {} representa al archivo encontrado.

  • Puedes encontrar y comprimir (simultáneamente) todos los archivos grandes (más pesados) usando
find . -type f -and -not -name "*.gz" -size +200k -exec gzip -v -f  {} +
  • En qué has estado trabajando últimamente? Encuentra archivos que sean más antiguos que 1 mes pero más nuevos que 2 meses.
find . -type f -newermt "$(date -d '5 months ago' '+%Y-%m-%d')" ! -newermt "$(date -d '4 month ago' '+%Y-%m-%d')" -exec ls -ltr {} +

29 de Noviembre, 2010

BUSCAR DENTRO DE LOS ARCHIVOS

Para encontrar dentro de un archivo de texto (por ejemplo, "words.txt") todas las líneas que comiencen con cualquier mayúscula, ejecutar

 grep '^[A-Z]' words.txt

Puede que estemos buscando cualquier línea que comience con mayúsculas o con un digito cualquiera. Las encontraremos con

 grep '^[A-Z1-9]' words.txt

Si estamos buscando líneas que terminen con minúsculas, ejecutamos

 grep '[a-z]$' words.txt

Si estamos simplemente buscando una palabra, ejecutamos

 grep 'patron' words.txt

lo cual buscara la secuencia "patron" dentro de cualquier palabra del texto. Si, por el contrario, queremos buscar todas las líneas donde NO APAREZCA "patron", usamos

 grep -v 'patron' words.txt

PD: Se recomienda activar la línea

 alias grep='grep --color=auto'

en el el archivo ".bashrc" que se encuentra en el home, para conseguir una busqueda con colores.


MANIPULANDO FOTOS/VIDEOS/PDF

12 de Diciembre, 2021

RECORTAR IMÁGENES (QUITAR BORDES)

Podemos recortar una imagen que esta rodeada por un fondo monocromático (de un solo color) y quedarnos sólo con la figura del centro usando el comando convert (ImageMagick):

convert original.png -trim -geometry 500x final_noborders.png

El comando -geometry 500x es opcional, y sirve para que la imagen final tenga un ancho de 500 pixeles (el alto se escala proporcionalmente).

23 de Enero, 2016

JUNTAR VARIAS FOTOS PNG O JPG EN UNA SOLA

Usando el comando convert:

convert image1.png image2.png image3.png image4.png image5.png  -append  final.png

De forma equivalente (mas compacto),

convert image{1..5}.png -append  final.png

Si las queremos pegar de izquierda a derecha, cambiamos -append% por +append%

convert image{1..5}.png +append  final.png

23 de Enero, 2016

REDUCIR EL TAMAÑO EN MEMORIA DE UN PDF (QUE PESE MENOS)

Si queremos que un archivo pdf ocupe menos memoria, pero que se vea igual, podemos utilizar el programa Ghostscript (gs):

gs -sDEVICE=pdfwrite -g10000x14151 -dNOPAUSE -dBATCH -dPDFFitPage  -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE   -sOutputFile=reduced-pdf.pdf original-file.pdf

Si queremos distintas resoluciones, podemos cambiar la geometría de la página cambiando el parámetro -g10000x14151 por distintas geometrías, o simplemente escribir. -sPAPERSIZE=a4. Si el archivo pdf está compuesto por imágenes solamente (como vimos abajo, al Juntar varias fotos en un PDF), podemos combinar pdfimages (para sacar las imágenes) con convert (para reducir el tamaño de las imágenes), y luego juntar todo con pdftk y sam2p. Es básicamente una mezcla de lo que mostramos en los trucos anteriores (ver abajo):

#!/bin/bash

# Pasar como argumento el pdf
for myPDF in "$1" #*.pdf
do
 folder=$(echo $myPDF|sed -e 's/.pdf//')
 mkdir -p "$folder"
 cd "$folder"
  cp ../"$myPDF" .
  pdfimages -j "$myPDF" myimages
  for i in myimages*ppm; do convert -geometry 800 "$i" "$i".jpg; done
  for f in myimages*.jpg;do sam2p -j:quiet "$f" PDF: "$f".pdf ; done
  rm "$myPDF" myimages*ppm myimages*jpg
  pdftk myimages*.pdf cat output newfile.pdf
  rm myimages*pdf

  pages_new=$(pdfinfo newfile.pdf | grep Pages|awk '{print $2}')
  pages_old=$(pdfinfo "../$myPDF" | grep Pages|awk '{print $2}')
  size_new=$(pdfinfo newfile.pdf | grep "File size"|awk '{print $3}')
  size_old=$(pdfinfo "../$myPDF" | grep "File size"|awk '{print $3}')
  if [ $pages_new == $pages_old ]; then
#   echo "They have" $pages_new "pages both"
   if [ $size_new -lt $size_old ]; then
    #echo "The new one is lighter:" $size_new "vs antiguos" $size_old
    echo "The new $myPDF is lighter."
    mv newfile.pdf "../$(echo $myPDF|sed -e 's/.pdf/_v2.pdf/')"
   else
    echo "The new $myPDF is heavier than before. Reducction did not work. Erasing new one..."
    rm newfile.pdf
   fi
  else
   echo "WARNING: the amount pages is not the same"
  fi
 cd ..
 rmdir "$folder"
done

21 de Marzo, 2022

CREAR GIF A PARTIR DE UN VIDEO

Si tenemos un video y queremos crear una animación gif, podemos utilizar el programa mplayer para separar el video en una serie de imagenes:

mkdir output
mplayer -ao null myvideo.mp4 -vo jpeg:outdir=output

o el programa ffmpeg:

mkdir output
ffmpeg -i myvideo.mp4 output/'%03d.png'

o el comando convert (ImageMagick):

mkdir output
convert myvideo.mp4 -transparent white output/frame-%03d.png

El formato %03d especifica el número fijo de dígitos para el nombre de archivo de salida (001.png, 002.png, ..., 500.png), donde cada imagen corresponde a un cuadro del video. Esto dividirá el video en varias fotos en formato jpeg o png, las cuales quedarán guardadas en la carpeta output/. La opción -transparent white quita el colór blanco de fondo y lo reemplaza por un fondo transparente. Luego, usando el comando convert, podemos fusionarlas en un solo archivo gif:

convert output/* output.gif

Si el gif avanza muy lento o es muy pesado, podemos simplemente eliminar cuadros intermedios. Por ejemplo, si tenemos 500 cuadros en los archivos 001.png, 002.png, ..., 500.png, podemos filtrar cada 5 cuadros utilizando

convert output/{001..500..5}.png output.gif

Esto usará sólo los cuadros 001.png, 006.png, 011.png, ..., y 496.png para crear el archivo gif.

A veces es posible optimizar el archivo gif (reducir su peso) con la opción -fuzz

convert output.gif -fuzz 75% -layers Optimize optimised.gif

Mientras mayor sea el valor de fuzz, más liviano queda el archivo.

30 de Octubre, 2015

ESCALAR IMÁGENES O FOTOS

Supongamos que tenemos una carpeta con fotografías en formato jpg, sacadas con una cámara digital. Si las fotos se sacaron con mucha resolución, van a ser muy pesadas, por lo que será difícil enviarlas por email, o bien estarán ocupando demasiado espacio de disco duro. Para reducir todas las fotos de tamaño con un solo comando, ejecutamos en dicha carpeta

 mkdir nuevas; ls -1 *.jpg | sed 's/.*/convert -geometry 1024x768 & nuevas\/&/' | sh

Esto crea una carpeta llamada "nuevas" dentro de la carpeta en cuestión, y en ella introducen las nuevas fotos escaladas a un tamaño 1024x768, que suele ser el tamaño standard de las fotos buenas, sin ser muy pesadas (~300Kb).

  • Es posible además poner un prefijo a los nombres de las fotos, añadiéndolo delante del símbolo "&". Por ejemplo, cambiando "&" por "s_&" provocará que una foto de origen, llamada foto.jpg, quede escalada en la carpeta "nuevas" con el nombre "s_foto.jpg".
  • Si no quieres crear una carpeta nueva dentro de la carpeta contenedora de fotos, sino que quieres dejar las fotos escaladas dentro de la misma carpeta; pero con distinto nombre, ejecuta
 ls -1 *.jpg | sed 's/.*/convert -geometry 1024x768 & .\/s_&/' | sh

lo cual creará las nuevas fotos escaladas, con el prefijo "s_" para identificarla de las originales.

30 de Octubre, 2015

SEPARAR UN PDF EN VARIAS FOTOS

Para extraer todas las fotos de un archivo PDF en formato JPG, podemos usar el programa pdfimages:

pdfimages -j myfile.pdf myimages

En el caso de que la opción -j no sea capaz de convertir las fotos en formato JPG, dejándolas en formato PPM (suele suceder), podemos convertirlas usando el programa convert:

for i in *ppm; do convert -geometry 800 "$i" "$i".jpg; done

La opción -geometry 800 escala la imágen a 800 pixeles de ANCHO, ajustando el alto para mantener las proporciones. También podemos usar

for i in *ppm; do convert -geometry x800 "$i" "$i".jpg; done

Con -geometry x800, se escala la imágen hasta tener 800 pixeles de ALTO, ajustando el ancho para mantener las proporciones.

10 de Junio, 2013

JUNTAR VARIOS PDF (O FOTOS) EN UN SOLO PDF

Si tienes muchos archivos en formato jpg, y quieres crear un solo documento pdf con ellos, esta es una forma de hacerlo. Necesitas tener instalados los programas sam2p y pdftk:

sudo apt-get install sam2p pdftk

Ahora convierte los archivos jpg en archivos pdf:

for f in *.jpg;do  sam2p "$f" PDF: "$f".pdf ; done

Con el siguiente comando, juntamos los archivos pdf recien creados (*.pdf) en un único archivo, llamado newfile.pdf:

pdftk *.pdf cat output newfile.pdf

Sin embargo, una forma más rápida de concatenar PDFs es usar ghostscript:

 gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile=newfile.pdf *.pdf

Todo en un solo programa

En base a estos comandos, hice un programa que, ejecutado dentro de una carpeta con fotos, crea un pdf un directorio más arriba (donde se encuentra la carpeta):

#!/bin/bash

for i in */
do
 if [ -f "$i" ]; then cd "$i"; fi
 # Gathering PNG pics
 if [ "$(find . -maxdepth 1 -iname "*png"|wc -l)" -gt "0" ]; then
  echo -n "Formato png en "
  pwd
  for f in *.png;  do   sam2p -j:quiet "$f" PDF: "$f".pdf;  done
  pdftk *.pdf cat output newfile.pdf
  rm *png.pdf
 # Gathering JPG pics
 elif [ "$(find . -maxdepth 1 -iname "*jpg"|wc -l)" -gt "0" ]; then
  echo -n "Formato jpg en";  pwd
  for f in *.jpg;  do   sam2p -j:quiet "$f" PDF: "$f".pdf;  done
  pdftk *.pdf cat output newfile.pdf
  rm *jpg.pdf
 else
  echo -n "Ninguna foto jpg o png encontrada en"; pwd
 fi

 new="../$(basename "$PWD").pdf"
 if [ -f newfile.pdf ]; then
  mv newfile.pdf "$new"
  echo "$(basename "$PWD").pdf created successfully."
 fi
 if [ -f "$i" ]; then cd ..; fi
done

29 de Noviembre, 2010

MENCODER: Manipulando videos

Primero, descarga el programa mencoder:

 sudo apt-get install mencoder

CONVERTIR FORMATO DE VIDEO

Para simplemente cambiar el formato de un video, por ejemplo, de ogv a avi, utiliza el comando

 mencoder pelicula.ogv -ovc copy -oac copy -o pelicula.avi

En este caso, el codec de video es simplemente copy, para que copie el video y el audio sin cambiar nada más que el formato. Para convertir de mp4 a MPEG, podemos utilizar

mencoder  planet-formation.mp4  -of mpeg -ovc lavc -lavcopts vcodec=mpeg1video  -oac copy -o pelicula.mpg

SUBTITULAR PELÍCULAS

En este caso, debes cambiar el codec de video por lavc y estar en posesión (descargar) los subtítulos en formato srt. Luego los pegas al video usando el comando

 mencoder pelicula.avi -sub subtitulos.srt -ovc lavc -oac copy -o pelicula-sub.avi

REDUCIR LA CALIDAD (AHORRAR MEMORIA)

Un comando asociado a mencoder es ffmpeg que funciona tanto en Linux como MacOS. Podemos reducir el tamaño de un video simplemente disminuyendo el bitrate:

ffmpeg -i input.mp4 -b 800k output.mp4

CORTAR UN VIDEO (Extraer una porción)

Para extraer una porción de un video, podemos ejecutar el comando

ffmpeg -ss 00:03:54 -I original-video.mp4   -c:v copy -t 00:01:12 -an  output-video.mp4

donde 00:03:54 representa el instante donde queremos que el nuevo video empiece, y 00:01:12 (1 minuto y 12 segundos) indica la duración del video desde el punto de inicio indicado anteriormente.


INTERNET

28 de Julio, 2021

rsync: Sincronizar archivos entre dos computadores

El programa rsync funciona de manera muy parecida a scp: el objetivo es copiar archivos desde o hacia un computador remoto. Sin embargo, la idea de copiar usando rsync es copiar los archivos nuevos o modificados, para evitar copiar todo el contenido de un directorio. De esta manera, es posible sincronizar dos directorios copiando lo estrictamente necesario

Traer archivos a tu computador

Si en un computador remoto (host) tu usuario es myname, y quieres copiar todas las carpetas Fe001, Fe002, Fe003, etc., ejecutamos:

rsync -avuz  myname@host:Fe* .

Si uno ejecuta el mismo comando inmediatamente despues, los archivos no se volveran a copiar, ya que el programa detecta que son identicos a los de la fuente. El programa genera una lista de archivos a copiar y luego copia. Aca usamos -a (modo archivo) -v (increased verbosity) -u (omitir archivos que existen en el destino y que tienen una fecha de modificacion mas nueva que el archivo fuente) y -z (comprimir durante la transferencia).

Generar la lista de archivos a copiar (debug)

Es bastante util generar la lista de archivos que se van a copiar para verificar que son efectivamente los archivos que queremos. Asi, no reemplazaremos archivos por equivocacion. Simplemente hay que omitir el directorio de destino:

rsync -avuz  myname@host:Fe*

El comando es casi identico al de arriba, pero hemos obviado el punto ( . ), que representa el directorio de destino (el directorio desde el cual estamos ejecutando el comando). El programa imprime la lista de archivos que se hubieran copiado si le hubieramos dado un destino.

Copiar solo ciertos archivos de los directorios en la fuente

rsync -avuz --include='*/' --include='*.dat' --exclude='*'  --prune-empty-dirs  myname@host:Fe* .

En este caso estamos sincronizando los mismos directorios, pero copiamos únicamente los archivos que terminan en .dat dentro de estos directorios. Para buscar como escribir patrones de archivos, leer el manual de rsync.

Copiar todo, EXCEPTO...

rsync -avuz --exclude='XDATCAR'  --exclude='OUTCAR' --exclude='*.xml'  myname@host:Fe* .

En este ejemplo, se copian todas las carpetas con todos sus archivos, excepto los archivos que se llaman "XDATCAR", "OUTCAR" y aquellos cuyo nombre termine en ".xml". Esto es particularmente útil para los usuarios de VASP.

Copiar solo los archivos más livianos/pequeños

rsync -avuz --max-size=200kb --prune-empty-dirs  myname@host:Fe* .

Con este comando estamos copiando todos los directorios que empiezan con Fe pero sólo si pesan menos que 200 kilobytes.

Puedes encontrar y comprimir (simultáneamente) todos los archivos grandes antes de transferirlos usando

find . -type f -and -not -name "*.gz" -size +200k -exec gzip -v -f  {} +

Mira el comando find.

Liberando espacio: eliminar archivos de la fuente después de copiarlos

rsync -avuz --prune-empty-dirs --remove-source-files myname@host:Fe* .

Este comando copia los archivos de la fuente al destino y luego los borra de la fuente, desde donde los copió. Los directorios vacíos van a quedar en la fuente de todas maneras, pero puedes eliminarlos usando

rmdir */*;   rmdir *

o

find . -type d -empty -delete

Recomiendo ejecutar el mismo comando sin --remove-source-files primero, sólo para asegurarse de que los archivos se copiaron bien antes de eliminarlos; pero en teoría solo los va a eliminar si los logró copiar existosamente.

Más información sobre rsync: https://phoenixnap.com/kb/rsync-exclude-files-and-directories