Comment s'amuser avec bash

Aide mémoires pour mon utilisation de la ligne de commande avec bash et Debian

dernière édition le à

manipulations de fichiers

générique

Quelques commandes utiles pour tout types de fichiers.

Liens

Il existe les liens symboliques et le liens physiques.

lien physique/dur :

graph LR s[source] --> disk l[lien dur] --> disk disk(secteur du disque)

lien symbolique :

graph LR s[source] --> disk l[lien symbolique] --> s disk(secteur du disque)

Et voici la commande qui permet d'en créer :

ln [-s] TARGET_PATH LINK_NAME

L'option -s défini le lien comme étant "symbolique".

💡 Plus d'infos sur ubuntufr

Créer une archive

Avec la commande zip.

Exemple pour créer un zip en cherchant récursivement dans les sous dossiers r et sans compression 0 :

zip -r0 FILENAME.zip PATH

Options :

mesurer l'usage disque

Avec la commande du.

du [OPTIONS] CHEMIN

options

Exemple

du -hs UN_DOSSIER_BIEN_REMPLI

afficher l'arbre

Avec la commande tree.

tree [OPTIONS] CHEMIN

options

gestion des permissions

umask

C'est un réglage global au niveau de l'utilisateur qui définit un masque permettant de réduire les permissions lors de la création de fichiers ou dossiers.

https://www.baeldung.com/linux/umask

ACL

Pour Access Control Lists. Ça correspond au mode "avancé" des permissions Linux. Il faut que le système de fichier soit compatible avec les ACLs. C'est le cas de Ext4, le système de fichier par défaut dans Linux.

Pour consulter les ACL d'un fichier/dossier, on peut lancer la commande :

getfacl CHEMIN

Avec un CHEMIN indiquant un fichier ou un dossier.

Cela affiche les permissions standard ainsi que les ACLs (s'il y en a).

Exemple de résultat :

# file: .
# owner: vincent
# group: vincent
user::rwx
group::rwx
other::---
default:user::rw-
default:group::rw-
default:other::r--
régler les permissions par défaut

On peut notamment définir quelles seront les permissions par défaut des nouveaux fichiers/dossiers créés.

Pour cela, on peut lancer la commande setfacl :

setfacl -m 'default:QUI::PERMISSIONS' 
supprimer les ACL

Pour retirer tout les réglages ACL d'un coup, on peu utiliser l'option -b avec setfacl :

setfacl -b CHEMIN

texte

écrire du texte

echo TEXTE > FICHIER

Rempli le contenu du FICHIER avec le TEXTE. ⚠️ Attention : ça peut tout écraser !

echo TEXTE >> FICHIER

Ajoute une nouvelle ligne contenant TEXTE à la fin du FICHIER.

micro

Micro est un éditeur de texte en CLI inspiré des programmes mainstream en GUI.

Il est dispo dans Debian :

sudo apt install micro

On peut ouvrir un fichier avec :

micro FICHIER

Si le fichier n'existe pas il sera créé lors de l'enregistrement.

raccourcis :

désactiver l'autocomplétion

Par défaut, la touche tab peut déclencher l'autocomplétion, ce qui peut être très génant lorsque l'on édite certains fichiers (par exemple des tsv).

Pour changer ce réglage on peut lancer la commande :

bind Tab InsertTab

changer la taille des tabulations

set tabsize SIZE

SIZE est le nombre de caractère de large des tabulations.

TSV

J'aime bien les fichiers tsv. TSV est un acronyme qui signifie "Tab Separated Values".

Pour afficher un tsv avec des jolies colonnes, on utiliser la commande column.

column -s$'\t' -t FICHIER

FICHIER étant le chemin vers le fichier tsv.
l'agument -s permet d'indiquer les données de chaque lignes sont séparés par des tabulations.

visidata

Visidata est un programme qu'on peut qualifier de TUI. C'est une sorte de tableur qui permet de faire plein de trucs avec les tableaux de différentes sortes.

https://www.visidata.org | Un tutoriel très sympa

Il est disponible dans Debian :

sudo apt install visidata

Pour le lancer, on l'appelle avec la commande suivante :

vd FICHIER

FICHIER étant le chemin vers le fichier tsv.

Raccourcis clavier :

les flèches directionnelles permettent de se déplacer spacialement.

titres des colonnes

Pour lancer visidata sans que la première ligne soit interprétée comme le titre des colonnes, on peut utiliser l'option --header 0.

Les colonnes seront alors sans noms. On peut les renommer en utisant la touche ^ (il faut taper deux fois on dirait).

Une fois dans le logiciel, on peut gérer les colonnes en tapant Shift + c. De cette façon, on arrive dans un affichage de tableau ou chaque ligne représente une colonne.

JSON

avec le programme jq.

cat FICHIER_JSON jq .

affiche le fichier JSON avec de la coloration synthaxique.

Par défaut, la sortie de jq est stylisée pour l'affichage. Avec l'option -r (pour raw), cela est désactivé et la sortie est en texte brut.

L'argument principal est un outil de filtrage qui ressemble à l'expression des objets en Javascript.

-

PDF

markdown vers PDF

Pour convertir très rapidement un fichier markdown en pdf, on peut utiliser pandoc. Par défaut le PDF sera généré via Tex, ce qui lui donne un style très universitaire.

pandoc FICHIER.md -o FICHIER.pdf

L'option -V geometry:margin=3cm permet de régler la marge de la page sur 3cm. J'ai dû mettre ça car par défaut, sur ma config, j'avais des marges trop imposante.

images

compresser une image

convert FICHIER_SOURCE FICHIER_DESTINATION

Ce sont les extensions des fichiers qui déterminent les format et les codecs utilisés. Par exemple :

convert avion.png avion.webp

La commande ci-dessus convertira un fichier png en fichier Webp.

convertir un dossier d'images

mogrify [...OPTIONS] GLOB_PATH

Parmi les options on peut mettre :

exemple pour réduire la tailles de photos de téléphone :

mkdir output
mogrify -auto-orient -resize 50% -quality 80 -monitor -path output/ *.jpg

ce script convertit tout les fichiers .jpg locaux vers le dossier `output.

ajouter une ombre à une image

Avec Imagemagick, il est possible d'ajouter une ombre à une image.

convert INPUT \( +clone -background black -shadow 30x15+0+5 \) +swap -background none -layers merge +repage OUTPUT

⚠️ la sortie doit être en PNG ou en Webp pour bénéficier de la transparence.

l'option -shadow permet de régler trois paramètres :

  1. le pourcentage d'opacité
  2. l'extension de l'ombre
  3. le décalage horizontal
  4. le décalage vertical

voir la section shadow du manuel Image Magick.

vidéos

encoder une vidéo

À l'aide de la commande ffmpeg.

ffmeg -i INPUT_PATH [...OPTIONS] OUTPUT_PATH

Conversion en x246, 720p à 3000kb/s (utile pour les vieux ordis pas très puissants) :

ffmpeg -i INPUT_FILE -b:v 3000k -c:v libx264 -s 1280x720 output.mkv

Pour de la mise en ligne web, on peut utiliser les derniers codecs VP8 ou VP9 et un fichier .webm. Mais cela est plus coûteux en processeur.

Voici un exemple qui converti en VP9, à 800kb/s en 1024x576px (max) :

ffmpeg -i INPUT_FILE -b:v 800k -s 1024x576 output.webm

encoder un WEBP animé

Comme les célèbres gif animés, il est aussi possible prduire de WebP animés. Le principal avantage est qu'ils sont considéré comme des images plutôt que comme des vidéos.

ffmpeg -i SOURCE -loop 0 -compression_level 6 -quality 15 output.webp

Les options :

documentation FFMPEG libwebp

retirer le son d'une vidéo

Pour rapidement retirer la piste son d'une vidéo sans ré-encoder la piste visuelle.

ffmpeg -i INPUT_PATH -c copy -an OUTPUT_PATH

L'extension du fichier (le conteneur) doit être compatible. Si c'est le même, pas de doute.

ajouter une bordure

Exemple de filtre pour ajouter une bordure rouge de 1px autour de la vidéo :

-vf "pad=width=iw+2:height=ih+2:x=1:y=1:color=red"

convertir un dossier de vidéos

Il n'y a pas de commande de groupe avec ffmpeg, on doit donc utiliser une boucle :

for VAR in PATH; do COMMAND... "$VAR" ... ; done

Combiné avec la commande de conversion expliquée si dessus.

Les options sont :

Exemple pour convertir des fichiers .mp4 en .webm :

for f in *.mp4; do ffmpeg -i "$f" -b:v 3000k "output/${f%.mp4}.webm"; done

Attention ! Il faut que le dossier de sortie soit créé au préalable !

capture d'écran

Cette commande va créer une capture d'écran à la même résolution que la vidéo source (sans redimentionner). Elle a le mérite de régler les soucis de ratio pour les vidéos dont les pixels ne sont pas carrés (comme tout les DVDs), grâce à -vf "scale=iw*sar:ih".

ffmpeg -hide_banner -loglevel error -ss TIME -i VIDEO_PATH -vf "scale=iw*sar:ih" -frames:v 1 OUTPUT_PATH

Avec VIDEO_PATH qui est le chemin de la vidéo source et OUTPUT_PATH le chemin vers le fichier image de sortie. L'extension de fichier va déterminer automatiquement la compression utilisée (.png, .jpg, .webp).

TIME définit le timecode de la capture à effectuer. Il peut être indiqué de deux façons :

  1. en heures:minutes:secondes.fractions_de_secondes [HH:]MM:SS[.m...]
  2. en nombre de secondes S

doc FFMPEG Time duration

Télécharger des vidéos de plateformes de streaming

Avec le logiciel yt-dlp

Installation

Pour Ubuntu, il est possible d'ajouter un PPA externe :

https://github.com/yt-dlp/yt-dlp/wiki/Installation#apt

Usage

yt-dlp [OPTIONS] URL

options

internet

Synchro

Synchroniser des fichiers avec rsync.

rsync [OPTIONS] SRC DEST

Pour un site distant :

rsync [OPTIONS] SRC USERNAME@HOST:PATH

Options importantes:

filtrage

C'est un peu complexe, mais il est possible de filtrer les fichiers avec des outils de filtrage. On peut utiliser pour ça l'option -f.

Exemple pour filtrer seulement une extension de fichiers :

-f'+ */' -f'+ *.EXTENSION_A' -f'- *'

On utilise successivement l'option, suivit d'une chaîne de caractère commençant par un symbole + pour inclure, ou avec un - pour exclure.
Il semble que l'ordre ait une importance, mais pas évident à comprendre. 😵‍💫

Comme souvent, le caractère * signifie "n'importe quel quantité de caractère sauf /". Pour intégrer les slashs, on peut utiliser **.

Si on veut inclure une extension supplémentaire, on peut ajouter après l'extension A : -f'+ *.EXTENSION_B'.

Exemple interactif

Voici un exemple de script interactif qui lance dabord un "dry run", puis qui demande une confirmation (avec gum ).

#!/bin/sh

gum spin --title "performing dry run..." --show-output -- rsync -ah --stats --dry-run --delete SRC DEST
gum confirm "perform sync ?" --default="No"

if test $? -eq 0
then
    rsync -ah --progress --stats --delete SRC DEST
else
    echo 'sync aborted'
fi

Requête d'URL

curl [OPTIONS] URL

options

créer des scripts

Quelques astuces souvent utilisée pour les scripts.

S'arrêter en cas d'erreur

Par défaut, Dash continue si une commande renvoie un code erreur. On peut inverser ce comportement grâce à l'option -e.

On peut facilement imaginer l'utiliser de base tellement elle semble le comportement attendu. La plupart des autres langages de programmation s'arrêtent dès qu'il y a une erreur.

Pour cela, on peut l'ajouter au shebang :

#! /bin/bash -e

(ou avec sh si on utilise dash)

Une autre façon de faire est d'utiliser set. Pour cela, on peut lancer (souvent au tout début de notre script) :

set -e

Demander la confirmation

read -p "Confirm? Y/n" -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    # do dangerous stuff
fi

Utiliser un argument ou stdin

#!/bin/bash

# on récupère le contenu via le premier argument
if test -n "$1"
then
    if test -f "$1"
    then
        content=$(cat "$1")
    else
        echo "file $1 does not exist"
        exit 1
    fi
else
    if test ! -t 0
    then
        content="$stdin"
    else
        echo 'provide a content using STD IN or a filename as first argument'
        exit 1
    fi
fi

echo "$content"

Envoyer des notifications

Avec la commande notify-send :

notify-send TITRE COMMENTAIRE

⚠️ ne pas oublier de mettre des guillemets lorsqu'il y a des espaces dans un des arguments

Malheureusement, impossible de passer des paramètres en arguments. Pour envoyé la sortie d'une commande on est obligé de faire comme ceci :

notify-send "$(COMMANDE)"

Modifier son shell

Créer un alias

On peut créer des alias de commande avec la commande alias, mais ils seront temporaires.

alias CMD='CMD'

Pour qu'il soit permanent, on peut l'écrire dans le fichier ~/.bashrc (quelque-part à la fin par exemple). Ensuite, on recharge ce fichier en lançant :

. ~/.bashrc

L'alias devrait maintenant être disponible depuis le shell Bash.

exemples d'alias :

L'exemple ci dessous rend la commande rm (remove) interactive. Ça fait office de sécurité en cas de fausse manip.

alias rm='rm -i'

une façon alternative de lister les fichiers accessible avec une seule touche.

alias ll='ls -alF'

Scripts perso

dirty sticker

un effet de sticker dirty pour des images avec de la transparence

#! /bin/bash
# DIRTY STICKER EFFECT
# add a sticker effect to a given input image
# image should have an alpha channel

# first argument is the input file name
# second is the border size (give it an integer, ex: 5 or 10)

set -e # stop the script in case of error

folder='sticker' # name of output folder

mkdir -p "$folder"

convert $1 \
    -bordercolor none -border 300 \
    -background white \
    -blur x1.5 \
    -adaptive-sharpen x7 \
    -alpha background -channel A -blur "x$2" -level 0,0% \
    -background black \
    -alpha background -channel A -blur x0.2 -level 0,0% \
    -emboss 0x1.5 \
    -spread .7 \
    -trim +repage \
    "$folder/$1"

Divers

Les trucs que je sais pas encore où les mettre. 😋

date

Avec l'utilitaire date.

Par défaut il utilise l'heure actuelle. On peut définir la date via l'argument --date=DATE ou -d. Il prend en charge plusieurs formatages différents, qui seront détectés automatiquement par le logiciel.
Cependant, pour lire une date au format timestamp UNIX, on la préfixe d'un @ :

date -d @1625394937000

Le formatage de sortie par défaut est un format littéral utilisant la langue par défaut. Pour le modifier, on le décrit après le signe +. Pour changer la langue de sortie, on rajoute avant la commande LC_TIME='<locale.encodage>'. Par exemple pour forcer la sortie en français :

LC_TIME='fr_FR.utf8' date

Pour fournir une date depuis un fichier, on utilise l'argument -f FICHIER. Mais il peut aussi servir à lire STDIN si on fourni - à cet argument, comme dans l'exemple suivant :

| date -f - 

Plein d'exemples sympa sur cette page :

https://www.zeuthen.desy.de/unix/unixguide/infohtml/coreutils/Examples-of-date.html

mailx

echo 'contenu' | mailx -s 'subject' -- coucou@hotmail.com

variables d'environnement

export MA_VARIABLE='ma super variable'

Pour vérifier si une variable d'environnement est définie :

printenv MA_VARIABLE

On peut l'utiliser comme une variable du shell, en rajoutant le $ devant.

echo $MA_VARIABLE

Pour la supprimer :

unset MA_VARIABLE

git

Le légendaire gestionnaire de versions.

Git cheatsheet

ramener une branche distante

Par exemple, si sur le dépot distant, il y a la branche et qu'elle n'existe pas localement.
Je peux faire :

git checkout NOM_BRANCHE_DISTANTE

Pas besoin de plus ! Si tout se passe bien, on reçoit :

La branche BRANCHE est paramétrée pour suivre la branche distante NOM_BRANCHE depuis NOM_DU_DEPOT.
Basculement sur la nouvelle branche NOM_BRANCHE

C'est super efficace !

publier une branche

Une fois que l'on est dans la branche que l'on souhaite publier (avec checkout), on utilise push avec -u, qui est une version raccourcie pour --set-upstream.

git push -u origin NOM_DE_LA_BRANCHE

différence entre les branches

Lorsque l'on est sur une branche (git checkout BRANCHE), on peut la comparer avec :

git diff AUTRE_BRANCHE

annuler un commit

Lorsqu'on vient de commiter une boulette. Ou que par exemple, on est pas dans la bonne branche, tant que celui-ci n'a pas été pushé, il est aisé d'annuler le dernier commit.

Pour cela on utilise la sous-commande reset :

git reset HEAD~

shutdown

Une commande pour éteindre l'ordinateur.

shutdown QUAND

L'argument peut être +MINUTES, ex : +60 pour "dans une heure", ou 20:30 pour éteindre à une heure définie, ou encore now (qui est en fait un alias de +0).

Si on omet l'argument, le défaut est +1, donc "dans une minute".

fzf

Un fuzzy-finder. fzf déclenche une interface de sélection parmis une liste en nous permettant de la filtrer de façon "diffuse" avec du texte.

Copie d'un fichier depuis un dossier

fzf se combine très bien avec find, un outil de recherche.

cp "$(find SOURCE -type f -name "*.EXT" | fzf)" DESTINATION

copie un fichier se trouvant n'importe où dans le dossier SOURCE vers le dossier DESTINATION.
Ici on cherche uniquement les fichier avec l'extension EXT.

beets

beets est un sacré logiciel de gestion de bibliothèque musicale.

importation incrémentale

J'utilise dans la config suivante :

import:
    incremental: yes
    incremental_skip_later: yes
    timid: yes
    detail: yes

albums multi-disques

Les albums multi-disques peuvent donner du fil à retordre à l'importeur. On peut essayer de merger l'album en deux fois, mais ça pose des problèmes avec le plugin convert.
Au final, je préfère les skipper pendant l'import et les importer par la suite en fournissant le chemin spécifique et grâce à l'option --flat.

suppression de musique

Pour retirer de la musique d'une collection gérée par beets, il vaut mieux toujours passer par lui plutôt que de supprimer directement les fichiers musicaux. Pour se faire on utilise la commande :

beet remove [-d] [-a] QUERY

Ce qui est pratique, c'est que ça fonctionne exactement comme la commande beet list QUERY. Donc on va souvent la lancer juste après avoir d’abord listé les fichiers.

Cette commande est interactive, elle demandera une confirmation avant de retirer les chansons de la bibliothèque.

Options intéressantes