Uno script bash multi-uso e configurabile

Pubblicato da Nicola Rainiero il 23-05-2013 (aggiornato il 19-06-2013)

Mi capita spesso di dover svolgere una o più operazioni come convertire/riscalare o rinominare una serie di immagini, video, file generici ecc. Se sono pochi lo faccio manualmente, in caso contrario modifico di volta in volta un file bash per eseguirli iterativamente da terminale. Tuttavia l'operazione non risulta molto agevole, perché dimentico quasi sempre di adattare e aggiornare qualche pezzo di codice.

Per questo motivo ho creato una sorta di template bash facilmente configurabile per: ripulirmi i file da spazi bianchi, punti e parentesi (li odio), impostare le estensioni interessate e il comando con le varie flag richieste. Inoltre lo ho dotato di un comodo debug, così prima di combinare danni irreparabili posso porvi rimedio leggendo l'output!

Prima di postare il codice riporto due esempi di utilizzo con i parametri di configurazione, ma come sempre anticipo le fonti che mi hanno aiutato a scriverlo:

Esempio 1: mogryfy

Obiettivo: scalare una cartella di immagini JPG riducendone la qualità

# SETTING START
COMMAND="mogrify"
EXTENSION_IN="jpg" # initial extension
EXTENSION_OUT="" # final extension
FLAG_B="-resize 400x400 -quality 40"
FLAG_M=""
FLAG_F=""
RM_FILE=false # if true, delete initial file after executing command
DEBUG=false # if true, print statement without executing any command
OPTION="2"

Esempio 2: avconv

Obiettivo: convertire una cartella di filmati da WEBM ad AVI ad alta qualità (cancellando gli originali)

# SETTING
COMMAND="avconv"
EXTENSION_IN="webm" # initial extension
EXTENSION_OUT="avi" # final extension
FLAG_B="-i"
FLAG_M="-b 2048k"
FLAG_F=""
RM_FILE=true # if true, delete initial file after executing command
DEBUG=false # if true, print statement without executing any command
OPTION="1"

Lo script bash

Anche se è una versione beta e in costante aggiornamento, sembra funzionare bene. Se avete qualche suggerimento o consiglio per migliorarlo, ogni vostro commento è ben accetto. Come farlo funzionare?

  • Basta copiarlo e salvarlo in un file di testo con estensione .sh;
  • ricordarsi di dargli il permesso di esecuzione;
  • lanciarlo dal terminale con: ./nome_file.sh direttamente nella cartella di destinazione o facendogli seguire il percoso della directory se differente da quella dove viene eseguito.

Questo è il codice da copiare:

#!/bin/bash
#
# SETTING:
COMMAND="avconv"
EXTENSION_IN="webm" # initial extension
EXTENSION_OUT="avi" # final extension
FLAG_B="-i"
FLAG_M="-b 2048k"
FLAG_F=""
RM_FILE=false # if true, delete initial file after executing command
DEBUG=false # if true, print statement without executing any command
OPTION="1"
#
# Description of the options:
#
# [0] just clean the file.EXTENSION_IN:
# replace empty space with "_", remove "(", ")", "-"
# [1] like 0 and execute:
# COMMAND FLAG_B file.EXTENSION_IN FLAG_M file.EXTENSION_OUT FLAG_F
# delete file.EXTENSION_IN if RM_file true
# [2] like 0 and execute:
# COMMAND FLAG_B file.EXTENSION_IN
# [3] a commented template
#
#

# Check if the user specifies a destination directory
if [ -n "$1" ]
then
directory=$1 # use this new working directory
else
directory=$PWD # use the same directory where you have launched the script
fi

eval cd $directory
OLDIFS=$IFS
IFS=$'\n'

for file in `ls *.${EXTENSION_IN}`
do
newfilename=`echo $file | sed 's/ /_/g'` # change empty spaces with "_"
newfilename=`echo $newfilename | sed 's/(//g;s/)//g'` # remove "(" and ")"
newfilename=`echo $newfilename | sed 's/-//g'` # remove "-"

# Remove the extension
newfile=${newfilename%.*}
newfile=`echo $newfile | sed 's/\./_/g'` # if there are some ".", replace them with "_"
if [ "$DEBUG" == true ]; then echo -e "Remove extension and other dots:\n$newfile"; fi

if [ "$DEBUG" == true ]; then echo "--------------------"; echo -e "Original file:\n$file"; \
echo -e "After cleaning:\n$newfile.$EXTENSION_IN"; fi

if [ "$file" != "$newfile.$EXTENSION_IN" ]
then
if [ "$DEBUG" == true ]; then echo -e "Rename file:\nmv $file $newfile.$EXTENSION_IN"; \
else mv $file $newfile.$EXTENSION_IN;fi
fi

case "$OPTION" in
0)
if [ "$DEBUG" == true ]; then echo -e "Nothing to do!"; fi
;;
1)
if [ "$DEBUG" == true ]
then
echo -e "Execute:\n$COMMAND $FLAG_B $newfile.$EXTENSION_IN $FLAG_M $newfile.$EXTENSION_OUT $FLAG_F";
else
eval $COMMAND $FLAG_B $newfile.$EXTENSION_IN $FLAG_M $newfile.$EXTENSION_OUT $FLAG_F \
|| { echo "$COMMAND failed! Check again the script"; cd $PWD; exit 1; }
fi

if [[ $RM_FILE == true && $DEBUG == true ]];
then echo -e "Delete:\nrm $newfile.$EXTENSION_IN"; fi
if [[ $RM_FILE == true && $DEBUG == false ]];
then eval rm $newfile.$EXTENSION_IN; fi
;;
2)
if [ "$DEBUG" = true ]
then
echo -e "Execute:\n$COMMAND $FLAG_B $newfile.$EXTENSION_IN"
else
eval $COMMAND $FLAG_B $newfile.$EXTENSION_IN \
|| { echo "$COMMAND failed! Check again the script"; cd $PWD; exit 1; }
fi
;;
# 3) # Add a new option using this template
# if [ "$DEBUG" == true ]
# then
# echo -e "Execute:\n((NEW COMMAND STATEMENT))"
# else
# eval ((NEW COMMAND STATEMENT)) \
# || { echo "$COMMAND failed! Check again the script"; cd $PWD; exit 1; }
# fi
# if [[ $RM_FILE == true && $DEBUG == true ]];
# then echo -e "Delete:\nrm $newfile.$EXTENSION_IN"; fi
# if [[ $RM_FILE == true && $DEBUG == false ]];
# then eval rm $newfile.$EXTENSION_IN; fi
# ;;
esac
done

# Return in the working directory
cd $PWD
exit 0



Potrebbero interessarti anche:

Nicola Rainiero

Ingegnere civile specializzato in geotecnica con l'ambizione di facilitare la propria attività lavorativa usando e creando software libero per un sapere condiviso e collettivo. Mi occupo anche di energie rinnovabili ed in particolare di geotermia a bassa entalpia. Sono da sempre appassionato di web design e modellazione 3D.