Some useful Bash commands


# Batch download
youtube-dl -i -F -a ~/Desktop/list.txt # Get the format
youtube-dl -i -f <format> -a ~/Desktop/list.txt # Use the format

# Automagically download the desired resolution
youtube-dl -i -f "bestvideo[height<=720]+bestaudio/best[height<=720]" -a ~/Desktop/list.txt

## Avoid throttling
youtube-dl -i --external-downloader aria2c --external-downloader aria2c --external-downloader-args "-j 8 -s 8 -x 8 -k 5M" -f mp4-240p -a ~/Desktop/list.txt
youtube-dl -f 18 -4 -i # Use IPv4

## Rate limit
youtube-dl -i -r 120k -a ~/Desktop/list.txt


# Batch download
wget -r -H -nc -np -nH --cut-dirs=1 -e robots=off -l1 -i ~/Desktop/list.txt

# Rate limit
wget --no-check-certificate --limit-rate 60k
wget --no-check-certificate --limit-rate 20k -i ~/Desktop/list.txt # Batch download

# Recursively fetch a directory
wget -r --no-parent --reject "index.html*" -e robots=off

## To avoid downloading the directory structure as well
wget -r -nH -nd -np -R index.html* -e robots=off

# Avoid the robots.txt issue
 -e robots=off  (See

# Download one type only
 -A jpeg,jpg,bmp,gif

# Use a user-agent
 -U -U "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv: Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8"

# So, get only fonts in an entire site
wget -r --no-parent --reject "index.html*" -e robots=off --limit-rate 60k -A otf,ttf,ttc,dfont 

Batch stuff

# Convert multiple video to audio
for i in *.mp4; do ffmpeg -i "$i" -vn "${i%mp4}mp3"; done
# Convert avi to mp4
for i in *.avi; do ffmpeg -i "$i" -c:a aac -b:a 128k -c:v libx264 -crf 23 -preset fast -profile:v baseline -level 3.0 -threads 2 "${i%avi}mp4"; done
# Convert mkv to mp4
for i in *.mkv; do ffmpeg -i "$i" -c:a aac -b:a 128k -c:v libx264 -crf 23 -preset fast -s 720x480 -threads 2 "${i%mkv}mp4"; done
# Convert .png to .jpg
for i in *.png; do mogrify -format jpg "$i" && rm "$i"; echo "$i converted to ${i%.*}.jpg"; done
# Same, but recursive
find . -iname '*.png' | while read i; do mogrify -format jpg "$i" && rm "$i"; echo "Converted $i to ${i%.*}.jpg"; done

# Randomize name
for i in *.mp4; do mv -i "$i" "${RANDOM}.mp4"; done

# Recursive copy
find . -name "*.zip" -exec cp -t ./direction_dir {} +
find . -type f -name "*.mp3" -exec cp {} /tmp/MusicFiles \ # Alternative
# Recursive deletion
find . -name "*.*" -print0 | xargs -0 rm -rf
# Recursive md5sum
find -type f -exec md5sum "{}" + > checklist.chk

# Recursive rename with modified date
j=1; for i in `find . -type f`; do mv -- "$i" "$(date +%Y-%m-%d_%H\'%M\'%S -r $i)_$j.${i##*.}"; j=$((j + 1)); done
## Will output: 2021-02-01_15'16'06_foo.webm
## Note: use IFS=$'\n' before the loop, for find to understand space in filename (mandatory on Windows)

# Recursive move in folders
for j in {01..31}; do for i in `find . -name "*\-$j\_*"`; do mkdir -p "$j" && cp "$i" "$j/"; done; done
## Use case: we have a bunch of files named 2021-02-01_15'16'06_bar.webm, we want them to be moved into the folder corresponding to their month (01 to 31)

Video to gif

# Simple
for i in *.mp4; do ffmpeg -i "$i" -an -s 320x240 -pix_fmt rgb24 -r 10 "${i%mp4}gif"; done
# Optimal with compression
for i in *.webm; do ffmpeg -i "$i" -vf fps=10,scale=320:-1:flags=lanczos,palettegen "$i.png"; ffmpeg -i "$i" -i "$i.png" -filter_complex 'fps=10,scale=320:-1:flags=lancz os[x];[x][1:v]paletteuse' "${i%webm}gif"; rm "$i.png"; done
# Recursive on the first 15 seconds with deletion of step's products
for i in `find . -name "*.webm"`;do ffmpeg -ss 0 -t 15 -i "$i" -vf fps=10,scale=320:-1:flags=lanczos,palettegen "$i.png"; ffmpeg -ss 0 -t 15 -i "$i" -i "$i.png" -filter_complex 'fps=10, scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse' "${i%webm}gif"; rm "$i.png"; rm "$i";done


# Get filename and extension
filename=$(basename -- "$fullfile")

Some poor workaround for Aura Creator saying there is no device

TL,DR: use Aura Creator with USB only, switch to 2.4GHz later.

So I bought an AZERTY ROG Falchion some days ago, working fine, was detected by Aura Creator… until the compatibility broke. Aura Creator was saying there is no device, but Aura Sync was working, and I could change my settings in Armoury Crate.

So, I reinstalled Aura Creator, losing my profiles. It was working until it broke again. I checked the log (DebugLog.log at \AppData\Local\Packages\XXXXX.AURACreator_xxxxx\LocalState\) and it was saying [Rescan] Get unsupported device ROG FALCHION, type: Keyboard which was weird. So, I messed around until I could get a grab on how this software was poorly designed.

The trick is: ROG Live Service detects connected devices and saves them to C:\ProgramData\ASUS\ROG Live Service\devices.ini. When the ROG Falchion is connected through USB only, there is one unique device in this file, with an US Layout. But when it is connected through 2.4GHz, there are two devices with two different PID. Somehow, the one with EU Layout isn't recognized by Aura Creator (but works fine with Aura Sync and Armoury Crate), despite the facts that Aura Creator has the correct .csv.

My workaround for users of EU layouts is quite simple: use Aura Creator with USB only, the 2.4GHz button off. Then you may be able to edit profiles to use when you'll switch to 2.4GHz later on. I hope this helps you.

Oh, and btw, before reinstalling Aura Creator you could save your profiles located in the \AppData\Local\Packages\XXXXX.AURACreator_xxxxx\ folder.

How do I stop my ROG Falchion wireless keyboard from rebooting Ubuntu?

For a more permanent solution, append the following config to /usr/share/X11/xorg.conf.d/40-libinput.conf:

Section "InputClass"
Identifier         "disable asus falchioh sys control"
MatchIsKeyboard    "on"
MatchProduct       "ASUSTeK ROG FALCHION System Control"
Option             "Ignore" "on"

Install python 3.6 on Ubuntu 20+ with distutils and pip support

sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update

Search and install something like python36-full. Then you can use pip with it:

python3.6 -m pip install [Package_to_install]

Python One-Liner Webserver HTTP

Python 2

python -m SimpleHTTPServer 8000

Python 3

python -m http.server 8000

Ripper un DVD multilangue avec mplayer/mencoder

La syntaxe de base :

mplayer -dumpstream dvdnav://1 -nocache -dumpfile my-duper-dvd.mpg

Il faut trouver le chapitre avec mplayer dvd://1. Une fois trouvé, on identifie l'AID de la langue souhaitée avec mplayer dvd://2 -identify :

subtitle ( sid ): 0 language: de
subtitle ( sid ): 1 language: de

Du coup notre commande devient :

mplayer -dumpstream dvdnav://2 -aid 129 -nocache -dumpfile my-duper-dvd.mpg

Si jamais des sous-titres sont lancés automatiquement, il suffit d'ajouter -nosub.

Remplacements multiples de termes dans plusieurs fichiers

La ligne de commande qui peut vous sauver plusieurs heures de boulot :

while read -r pattern replacement; do sed -i -- "s/$pattern/$replacement/" *.tex ; done < patterns.txt

Ça remplace toutes les occurrences de plusieurs termes dans tous les fichiers d'un type donné.

Ça prend en entrée un fichier patterns.txt constitué d'une liste comme suit :

foo bar
truc muche

Où foo et truc seront remplacés respectivement par bar et muche.


Les DNS de FDN : bookmarklet

Redirects a youtube page to an one. Copy and paste this into the url field of a browser bookmark.

javascript:(window.location.href.includes(""))?location.href=window.location.href.replace("",""):console.log('not a youtube page')

Chargement dynamique d'un Javascript en fonction de l'existence d'une classe dans le DOM

function isAnyClassOutThere(class,tag){
   // On transforme le string passé en paramètre en une expression régulière
   //(sans cela, test() ne retournera rien)
   var regExpClass = new RegExp(class);

   // S'il n'y avait pas de tag passé en paramètre, on considère que l'on regarde
   // tous les tags
   var tag = tag || "all";
   var elm = (tag == "all") ? document.all : document.getElementsByTagName(tag);

   var result = false;

   // Pour chaque élément que l'on a récupéré dans elm
   for(var i=0; i < elm.length; i++){

      // On test la correspondance
         result = true;

         // On sort de la boucle (pas très joli, mais évite de faire un return 
         // dans une boucle)

return result;
function loadJS(url){
   // On crée un élément script
   var elm=document.createElement("script");

   // On lui attribue une url
   elm.setAttribute("src", url);

   // On renseigne le type
   elm.setAttribute("type", "text/javascript");

   // Enfin, on l'ajoute en temps qu'enfant de l'élément head
   if(isAnyClassOutThere("galerie", "ul")){

Remplacement propre des caractères spéciaux en PHP

function filtre($string) {
    $search = array ('@(é|è|ê|ë|Ê|Ë)@','@(á|ã|à|â|ä|Â|Ä)@i','@(ì|í|i|i|î|ï|Î|Ï)@i','@(ú|û|ù|ü|Û|Ü)@i','@(ò|ó|õ|ô|ö|Ô|Ö)@i','@(ñ|Ñ)@i','@(ý|ÿ|Ý)@i','@(ç)@i','@( )@i','@(^a-zA-Z0-9_)@', '@(\'|\.)@');
    $replace = array ('e','a','i','u','o', 'n', 'y', 'c','-','', '');
    $in = preg_replace($search, $replace, $string);
    $in = preg_replace('/([^.a-z0-9]+)/i', '-', $string);
    return strtolower($string);

Désactiver le touchpad avec Bash

# Enable/Disable touchpad
# $device is found by using "xinput list"

mode="$(xinput --list-props $device | grep $property | cut -d':' -f2)"

if [ $mode -eq "1" ]
    xinput --set-prop $device $property 0
    xinput --set-prop $device $property 1

Oubliez votre lien d'administration avec Javascript !

Appuyer 3 fois sur Entrée mènera au lien d'administration :

function keyboardAuth(redirection) {
    var enterCount = 0;

    document.addEventListener("keypress", function(event) {
        var keycode = (event.keyCode ? event.keyCode : event.which);
        if(keycode == '13'){
            if(enterCount >= 3){
                enterCount = 0;
                window.location = redirection;
        setTimeout(function(){ enterCount = 0; },2000);


Scrolling doux vers une ancre

$('a[href*=#]').on('click', function(event){
$('html,body').animate({scrollTop:$(this.hash).offset().top}, 700); });

Un lien « Retour en haut » dynamique

<div class="relative">
    <div class="toTop">
        <a href="#top" title="Retour en haut">
            Retour en haut
<footer id="footer">
.relative {

.toTop {
function toTop(element,footer){
    var scroll = $(window).scrollTop();
    var maxScroll = $(window).height() * 0.4;

    if(scroll > maxScroll)

    if($(element).offset().top + $(element).height() >= $(footer).offset().top - 10)
        $(element).css('position', 'absolute');
    if($(document).scrollTop() + window.innerHeight < $(footer).offset().top)
        $(element).css('position', 'fixed');

$(window).scroll(function() {

$(window).resize(function() {

Effet parallax avec jQuery

* Adds a parallax effect to a background image
* (position:fixed;no-repeat;background-size:42%;)
* element : the element with a background image
* percent : percent of the background-size (0.42)
* height : height of the background image
* width : width of the background image
* factor : factor of speed (the lower the faster)
* reference : the element bottom-placed to get the total
*             height of the page
* author : Guillaume Litaudon  <>

function parallax(element,percent,height,width,factor,reference){
    var winWidth = $(window).width();
    var winHeight = $(window).height();

    var sizePercent = percent == 1 ? height : ((winWidth*percent)/width)*height;

    var maxScroll = -(sizePercent - winHeight);
    var speed = factor*($(reference).offset().top / winHeight);
    var yPos = -($(window).scrollTop() / speed);
    yPos = yPos >= 0 ? 0 : yPos;
    yPos = yPos >= maxScroll ? yPos : maxScroll;
    var coords = '0 '+ yPos + 'px';

    $(element).css({ backgroundPosition: coords });

function goGoParallaxEffect(){
    /* La taille dépend de si l'on est en-dessous
    * de pictureWidth ou non
    var pictureHeight = 1080;
    var pictureWidth = 388;

    if($(window).width() > pictureWidth)

$(window).scroll(function() {

$(window).resize(function() {

Optirun sous Linux

Après plusieurs tests, il apparait que la meilleure ligne de commande sur mon système soit :

LD_PRELOAD=/usr/lib/x86_64-linux-gnu/  __GL_SYNC_TO_VBLANK=0 vblank_mode=0 PRIMUS_SYNC=1 primusrun %command%
## Alternative plus simple
env vblank_mode=0 __GL_SYNC_TO_VBLANK=0 VGL_READBACK=pbo optirun %command%

Pour GZDoom :

## 100+ fps but use Intel
vblank_mode=0 ENABLE_PRIMUS_LAYER=1 optirun -b primus gzdoom
## 75+ fps with Nvidia
vblank_mode=0 ENABLE_PRIMUS_LAYER=1 VGL_READBACK=pbo __GL_SYNC_TO_VBLANK=0 primusrun gzdoom
## Or simply
vblank_mode=0 primusrun gzdoom

Lancer des jeux Steam avec Proton + Optirun

Utiliser ceci comme options de lancement des jeux :

PROTON_NO_ESYNC=1 PROTON_USE_WINED3D=1 env vblank_mode=0 __GL_SYNC_TO_VBLANK=0 VGL_READBACK=pbo optirun %command%

Anacron chez Gandi

Pour Nextcloud

php -f occ db:add-missing-indices

Faire une tâche cron pour actualiser la liste des périphériques qui se connectent :

1@hourly 0 nextcloud php -f /srv/data/web/vhosts/my-vhost/htdocs/cron.php > /tmp/nextcloud.log 2>&1
1@hourly 0 freshrss php -f /srv/data/web/vhosts/my-vhost/htdocs/rss/app/actualize_script.php > /tmp/nextcloud.log 2>&1

Pour FreshRSS

Supprimer les sauts de ligne en trop dans un sous-titre en .srt

On convertit avec iconv (et détection automatique de l'encoding avec uchardet), car certains sous-titres sont en utf16. Puis on supprime les retour chariot Windows qui empêchent de faire quoi que ce soit. On supprime alors les lignes commençant par un newline. On rajoute un newline aux lignes ne comportant que l'index. Enfin, on supprime la première ligne (qui alors ne contient qu'un newline).

for file in *.srt; do cp "$file" "$file.bak"; encoding=$(uchardet "$file"); iconv -f $encoding -t utf8 "$file" -o "$file.utf8"; tr -d '\r' < "$file.utf8" | sed '/^$/d' | sed 's/^\([[:digit:]]\+\)$/\n\1/gm' | tail -n +2 > "$file"; rm "$file.utf8"; done