Contexte
La recherche de doublons est un besoin assez frĂ©quent, lâimplĂ©mentation en bash nâest pas nĂ©cessairement simple.
Je vous propose une solution trĂšs simple Ă mettre en Ćuvre utilisant jq
.
Exemples
Pour rechercher une valeur en double, il faut mĂ©moriser cette valeur quâon appellera la clĂ© et garder il faut Ă©galement mĂ©moriser un identificateur correspondant Ă cette valeur.
De maniĂšre gĂ©nĂ©rale, vous devrez donc prĂ©voir du code pour construire la valeur de la clĂ© et un mĂ©canisme pour construire lâidentificateur.
Cas dâun fichier texte
Supposons un fichier texte dans lequel on souhaite retrouver les lignes en doubles, sans changer lâordre du fichier.
Dans ce cas la valeur Ă mĂ©moriser est le contenu de la ligne (ce sera notre clĂ©) et lâidentificateur sera, par exemple, le numĂ©ro de la ligne.
Il sera possible, par exemple, de supprimer les derniĂšres lignes en double, sans pour autant changer lâordre du fichier.
Cas de fichiers sur le disque
Si on souhaite rechercher des fichiers ayant le mĂȘme contenu dans une arborescence donnĂ©e, la clĂ© devient le contenu du fichier, comme cela nâest pas acceptable (trop de mĂ©moire et trop lent), on passe par un calcul de hachage, par exemple Ă lâaide de sha512sum
et, dans ce cas, lâidentificateur sera le nom du fichier.
Lâalgorithme
Initialisation
Lâinitialisation est Ă faire une seule fois au dĂ©but du traitement. On va utiliser une variable globale pour rĂ©pondre au cas gĂ©nĂ©ral.
declare -g _entries_json_='{}'
Il sâagit ici de construire un objet JSON
vide.
Itération
_key_=âŠLe truc potentiellement en doubleâŠ
_id_=âŠUn truc permettant dâidentifier les doublesâŠ
_entries_json_="$(
jq -c --arg key "${_key_}" --arg id "${_id_}" '.[$key] |= .+ [ $id ]' <<<"${_entries_json_}"
)"
Attention, la clĂ© doit est une chaĂźne de caractĂšre raisonnable : en particulier, elle ne doit pas ĂȘtre trop longue.
RĂ©sultat
Une fois toutes les valeurs stockées dans la structure JSON
, on supprime toutes les entrĂ©es qui nâont pas de double :
_resultat_="$(
jq '[ to_entries[] | select( .value | length >1 ) ] | from_entries' <<<"${_entries_json_}"
)"
Et pour dĂ©tecter sâil y a des doubles, il suffit regarder le nombre dâentrĂ©es, par exemple :
if [ -n "$( jq -r 'to_entries[] | length' <<<"${_resultat_}" )" ] ; then
echo 'Les doubles:'
jq '.' <<<"${_resultat_}"
else
echo 'Pas de double'
fi
Exemple de code concret
La bibliothĂšque:
function init_duplicate {
declare -g _entries_json_='{}'
}
function add_for_duplicate {
local -r _key_="$1"
local -r _id_="$2"
_entries_json_="$(
jq -c --arg key "${_key_}" --arg id "${_id_}" '.[$key] |= .+ [ $id ]' <<<"${_entries_json_}"
)"
}
function finalize_duplicate {
_entries_json_="$(
jq '[ to_entries[] | select( .value | length >1 ) ] | from_entries' <<<"${_entries_json_}"
)"
}
Imaginons le code suivant :
init_duplicate
add_for_duplicate 'k1' 'v1-1'
add_for_duplicate 'k1' 'v1-2'
add_for_duplicate 'k2' 'v1-2'
add_for_duplicate 'k2' 'v2-2'
add_for_duplicate 'k3' 'v3-1'
jq '.' <<<"${_entries_json_}"
Le résultat intermédiaire sera :
{
"k1": [ "v1-1", "v1-2" ],
"k2": [ "v2-1", "v2-2" ],
"k3": [ "v3-1" ]
}
Ensuite pour obtenir que les doubles, on peut faire :
finalize_duplicate
jq '.' <<<"${_entries_json_}"
Et voilĂ Â :
{
"k1": [ "v1-1", "v1-2" ],
"k2": [ "v1-2", "v2-2" ]
}
Utilisation de la mémoire
Cette solution est assez gourmande en mĂ©moire et en CPU, mais il est trĂšs facile de lâadapter et de stocker le rĂ©sultat dans un fichier (au dĂ©triment du temps dâexĂ©cution, bien Ă©videment).
Le principal intĂ©rĂȘt de cette solution Ă©tant quâelle est assez gĂ©nĂ©rique et sâadapte Ă presque tous les cas.
Références
- TĂ©lĂ©charger le fichier duplicate-api.sh đ„ si vous souhaitez essayer cette micro bibliothĂšque.
- TĂ©lĂ©charger l'exemple complet đ„.
- Installation de
jq
:- Billet du blog đ Installation de jq,
- Page officielle, en anglais,
- [Comment installer JQ sur Mac en ligne de commande ?]
https://www.it-swarm-fr.com/fr/command-line/comment-installer-jq-sur-mac-en-ligne-de-commande/825918790/
(lien cassĂ©) (Je nâai pas testĂ©, nâayant de pomme)
኿