#!/bin/bash
##################################################
# Fichier  : s3f
# But      : recherche de fichiers personalisée
# Détails  : xav search-tool
#            par analogie avec gst, gnome-search-tool
#            nécessite zenity
# 20200716 : dossiers réseaux scannables par find, pas par updatedb (cf. find_network)
# 20180105 : S3F_HISTO (car découvert on peut lancer s3f depuis Alt-F2 sous Raspbian => on perd historique .bash_history)
# 20141117 : nouveau nom=s3f, super fast file finder
# 20120417 : nouveau nom=s, ancien nom=xst (xav search tool)
# 20111103 : TODO ajouter la possibilité de chercher du texte dans tous les fichiers texte des catalogues
# 20120308 : TODO mettre condition test existence fichier $i/.VIDE_NE_PAS_EFFACER_pour_xst
#            pour éviter d'écraser l'index avec un index vide
# pastebin : http://pastebin.com/EkBVLdjf
# nécessite : sudo apt install locate  # sur raspbian
####################fin_entete####################
##################################################

# TODO :
# - IMPORTANT : dossiers privés/publics
# - ne pas effacer un catalogue où media absent
#

SEARCHDIR=/media

# 1. constantes
verbose="FALSE"
afficher="FALSE"
EDITEUR=vim

# 2. variables par défaut
display_duration="FALSE"
lancerDIR="FALSE"
S3F_TMP=/tmp/s3f
S3F_HISTO=$0.histo

-d ${S3F_TMP} ] || mkdir ${S3F_TMP}
fResultats=$(mktemp ${S3F_TMP}/s3f_XXXXXXXX)
maxi_a_lancer=10

# variables à personnaliser
# dossier contenant les catalogues
DIR_CATALOGS=/home/pi/3en1/divers/mon_updatedb
# définir ici les dossiers à scanner
dossiers="$HOME"    # 20200716 comprend nouveaux dossier cryptmount
dossiers="$dossiers;/media/pi/A-300GB"
dossiers="$dossiers;/media/pi/B-650GB"
find_network="/media/fbx"

#############################################################################
# TODO :  ajouter décompta nb dossiers et fichiers par dossier de ${dossiers}
#############################################################################


# fonctions
on_cherche () {
#  lister resultats
#  (les enregistrer dans catalogues)
if $afficher "TRUE" ] ; then
 echo Arguments de recherche :
 echo $*
fi

tmp1=$(mktemp ${S3F_TMP}/tmp1_XXXXXXXX) tmp2=$(mktemp ${S3F_TMP}/tmp2_XXXXXXXX)
x=$*
x="$@"
rm $fResultats 2>/dev/null

# 1. parcourir les catalogues et rechercher premier terme
# TODO : locate peut chercher en une passe
# dans tous les dossiers donnés en un seul paramètre  (-d database1:database2:...)
set $x
for in $(ls -1 ${DIR_CATALOGS} | grep ".updatedb" | grep -v lisezmoi.txt | grep -v "7z$")
do
  echo LOCATE -d ${DIR_CATALOGS}/$d -"$1"
  locate -d ${DIR_CATALOGS}/$d -"$1"
done $tmp1

 shift
 # 2b. rechercher termes suivants
 while [ ! "x$1" "x" ]
 do
   grep -"$1" $tmp1 >> $tmp2  # recherche insensible à la casse
   mv $tmp2 $tmp1
   shift
 done
 cat $tmp1 >> $fResultats

# 2. parcourir les catalogues réseau
set $x
for in $(ls -1 ${DIR_CATALOGS} | grep ".find_network" | grep -v lisezmoi.txt | grep -v "7z$")
do
  grep -"$1" ${DIR_CATALOGS}/$d
done $tmp1

shift
while [ ! "x$1" "x" ]   # 2b. rechercher termes suivants
do
  echo GREP -"$1" $tmp1 '>>' $tmp2  # recherche insensible à la casse
  grep -"$1" $tmp1 >> $tmp2  # recherche insensible à la casse
  mv $tmp2 $tmp1
  shift
done
cat $tmp1 >> $fResultats
rm $tmp1 $tmp2 2>/dev/null

#~ rm $fResultats
}

on_cherche_second_chance_OLD () {
 zenity --info --title "En construction" --text "Aucun résultat. on_cherche_second_chance bientôt dispo (fuzzy search). Recherche sur des termes voisins à la google."
}

on_affiche_ou_lance_resultats () {
#  lancer resultats
# $1 = LANCER => lancer première ligne
if "x$1" "xLANCER" ] ; then
     if $lancerDIR "TRUE" ] ; then
         echo "Lancement de la première ligne DOSSIER parent"
         f="$(dirname $(head -1 $fResultats))"
         nemo "$f"
     else
         echo "Lancement de la première ligne"
         f="$(head -1 $fResultats)"
         #~ xdg-open "$(head -1 $fResultats)"
         nemo "$(head -1 $fResultats)"
     fi

 if [ ! $? ] ; then
  zenity --info --title "Erreur" --text "Impossible de trouver le fichier $f" --timeout 5
 fi
 return 0
fi

res=$(mktemp ${S3F_TMP}/res_XXXXXXXX)
IFS=$'\n'
#~ cat $fResultats |
  #~ zenity --width 1100 --height 500 --list \
         #~ --title "Recherche : $lignecom" --text "Choisir une ou plusieurs lignes "  \
         #~ --multiple --column "Fichiers/dossiers" | 
         #~ tr '|' '\n' > $res
cat $fResultats |
  zenity --width 1100 --height 500 --list \
         --title "Recherche : $lignecom" --text "Choisir une ou plusieurs lignes "  \
         --multiple --column "Fichiers/dossiers" 
         tr '|' '\n' $res
# lancer chaque ligne sélectionnée
nbselect=0
while read rr
do
  # limiter nb maxi pour ne pas surcharger machine
  nbselect=$((nbselect+1))
  echo nbselect=$nbselect
  echo maxi_a_lancer=${maxi_a_lancer}
  echo
  if "${nbselect}" -gt "${maxi_a_lancer}" ] ; then
   zenity --info --title Avertissement --text "Vous ne pouvez pas lancer plus de 10 lignes"
   exit 1
   else

    # lancement xdg-open
     if $lancerDIR "TRUE" ] ; then
       echo nemo "$(dirname "$rr")"
       #~ xdg-open "$(dirname "$rr")"
       nemo "$(dirname "$rr")"
      else
      echo xdg-open "$rr"
      #~ xdg-open "$rr"
      nemo "$rr"
     fi
     sleep 1
 
  fi
done $res

rm $res

# DEBUG ajouté en dernier (au cas où dysfonctionnement)
rm $fResultats
}

locmaj () { 
for in $(echo $dossiers | tr ';' ' ')
do
#nomcat=$(echo $i|sed 's/\//_/g')
 if -d "$i" -a $(ls "$i" -l 2>/dev/null | wc -l) -gt ] ; then
 nomcat=$(echo $i|sed 's/\//_/g').updatedb
 cd "$i"
  echo "$(date +%c) updatedb --output=$DIR_CATALOGS/$nomcat --localpaths=$i ..."
  echo "$(date +%H:%M:%S) [  OK  ] $i"
  #~ updatedb -l 0 -o $DIR_CATALOGS/$nomcat -U $i           # version linux mint
  updatedb --output=$DIR_CATALOGS/$nomcat --localpaths=$i 2>/dev/null  # version ARM raspbian
 else
  echo "$(date +%H:%M:%S) [ABSENT] $i"
 fi
done
# dossiers réseau pas acceptés par updatedb
# COORECTION : cf. option --netpaths='path1 path2...'
#              https://man7.org/linux/man-pages/man1/updatedb.1.html
for in $(echo $find_network | tr ';' ' ')
do
 if -d "$i" -a $(ls "$i" -l 2>/dev/null | wc -l) -gt ] ; then
 nomcat=$(echo $i|sed 's/\//_/g').find_network.txt
 cd "$i"
  echo "$(date +%c) find $i -type f > $DIR_CATALOGS/$nomcat ..."
  echo "$(date +%H:%M:%S) [  OK  ] $i"
  find $i -type f $DIR_CATALOGS/$nomcat
 else
  echo "$(date +%H:%M:%S) [ABSENT] $i"
 fi
done
echo "$(date +%H:%M:%S) update fini"
}

show_catalogs () {
echo
echo '#################
Variable dossiers
#################'
for in $(echo $dossiers | tr ';' ' ')do
 echo "- $i"
done
echo
echo '###################
ls -l $DIR_CATALOGS
###################'
ls -l $DIR_CATALOGS

echo "
Pour éditer la liste des catalogues,
modifier directement la variable dossiers dans
le script $0"
}

aide_s3f () {
echo "$(basename $0)"
echo "   s3f = super fast file finder"
echo "Recherche ultra-rapide à partir de catalogues"
echo "créés avec updatedb."
echo "La recherche se fait avec locate (premier terme),"
echo "et grep (termes éventuels suivants)."
echo ""
echo "Utilisation : $(basename $0) [OPTION]... terme1 [terme2] [terme3] ..."
echo ""
echo "Options courtes :"
echo "  -d   dir (dossier)" 
echo "       affiche les résultats dans zenity, avec lancement du dossier de la ligne choisie" 
echo "  -D   liste des dossiers indexés après avoir effacé l'écran" 
echo "  -h   cette aide" 
echo "  -i   interactif (interface graphique)" 
echo "       affiche une boîte de dialogue zenity demandant d'entrer la ligne de commande complète" 
echo "  -n   nemo dans dossier catalogues" 
echo "  -N   nemo dans dossier parent première ligne trouvée" 
echo "  -l   lister" 
echo "       affiche les résultats dans le terminal (utile pour traitement par shell)" 
echo "  -L   liste des dossiers indexés" 
echo "  -s   start (lancer) [DEFAUT]" 
echo "       affiche les résultats dans zenity, avec lancement d'une ligne par double clic" 
echo "  -S   lance la première ligne trouvée" 
echo "  -p   presse-papier"
echo "  -u   update" 
echo "       mise à jour des catalogues définis dans la variable locale dossiers," 
echo "       définies dans le script même." 
echo "  -U   update et quitter console" 
echo "  -z   interactif (interface graphique)" 
echo ""
echo "Exemples :"
echo "s3f -u"
echo "       met à jour les catalogues"
echo ""
echo "s3f scripts traitement image"
echo "       recherche les fichiers dont le nom complet contient les mots"
echo "       'scripts' 'traitement' 'image' dans n'importe quel ordre,"
echo "       et affiche la liste dans une fenêtre (zenity)."
echo "       Double-cliquez sur un élément ou bien sélectionner plusieurs lignes"
echo "       et appuyez sur Ouvrir."
echo ""
echo "s3f -d facture phon free"
echo "       recherche les fichiers dont le nom complet contient les mots"
echo "       'facture' 'phon' 'free' dans n'importe quel ordre"
echo "       et affiche la liste dans une fenêtre (zenity)."
echo "       Double-cliquez sur un élément ou bien sélectionner plusieurs lignes"
echo "       et appuyez sur Ouvrir pour ouvrir le dossier parent."
}

verif_dirs_catalogs () {
 if [ ! -d $DIR_CATALOGS ] ; then
 echo Le dossier $DIR_CATALOGS n\'existe pas. FIN.
 echo Pour le créerlancer ceci :
 echo mkdir $DIR_CATALOGS
 exit 1
fi
}

reprendre_histo () {
:
}

ligne_commande () {
# 0. premier contrôle : ligne de commande
if $# ] ; then
  aide_s3f
  return 0
fi

lignecom="$@"
#~ echo "$@" >> ${S3F_HISTO}

while getopts "defghilnsSpuULDzN" option
do
  case "$option" in
    l# search / chercher dans fichiers textes des catalogues
       afficher="FALSE"
       shift $((OPTIND-1))
        echo ON CHERCHE 1
       on_cherche "$@"
       $(wc -l < $fResultats) -eq ] || cat $fResultats
       rm $fResultats
       exit 1
       ;;
    D|L
       clear
       show_catalogs
       exit 1
       ;;
    d# lancer dossiers
       shift $((OPTIND-1))    # ici shift indispensable, ai reprendre tout code pour 
       lancerDIR="TRUE"       # lancer opérations en-dehors du while getopts
       afficher="TRUE"
       echo ON CHERCHE 2
       on_cherche "$@"
       $(wc -l < $fResultats) -eq ] || on_affiche_ou_lance_resultats
       exit 1
       ;;
    e# search / chercher
       echo ON CHERCHE 3
       on_cherche "$@"
       echo $EDITEUR $fResultats
       $EDITEUR $fResultats
       return 0
       ;;
    f# fuzzy search
       banner fuzzy
       banner en_cours
       zenity --info --title Information --text "Option FUZZY En construction."
       echo ON CHERCHE 4
       on_cherche fuzzy "$@"
       $EDITEUR $fResultats &
       sleep 5
       rm $fResultats
       exit 1
       ;;
    gshift
       recherche_gnome_search_tool "$@"
       return 0
       ;;
    h# aide
       aide_s3f
       return 0
       ;;
    iinteractif
       return 0
       ;;
    n# nemo
       nemo $DIR_CATALOGS
       return 0
       ;;
    s# recherche [DEFAUT]
       afficher="TRUE"
       shift
       echo ON CHERCHE AAA
       lancer_rechercheA "$@"
       return 0
       ;;
    S# recherche puis lancement 1er résultat
       afficher="TRUE"
       shift
       recherche_puis_lancement_premier_resultat "$@"
       return 0
       ;;
    N# recherche puis lancement 1er résultat
       afficher="TRUE"
       shift
       recherche_puis_lancement_premier_resultat_dossier "$@"
       return 0
       ;;
    t# lancer / launch [DEFAUT]
       display_duration="TRUE"
       ;;
    p# relancer xst avec le presse-papier
       if $(which xsel) then
        echo Veuillez installer xsel
        echo FIN
        zenity --info --title Information --text "xsel n'est pas présent, veuillez l'installer"
        exit
       fi
       #~ echo $0 "$(xsel -b | head -1 | cut -c-50)"
       $0 "$(xsel -b)"
       return 0
       ;;
    ulocmaj
       return 0
       ;;
    Ulocmaj
       echo "kill -9 $PPID dans 1s"
       sleep 1
       kill -$PPID
       return 0
       ;;
    zecho interactif
       interactif
       return 0
       ;;
  esac
  shift $((OPTIND-1))
done
# aucune option : par défaut on_cherche puis on_affiche_ou_lance_resultats
afficher="TRUE"

echo ON CHERCHE DEFAUT
lancer_rechercheA "$@"
}

recherche_puis_lancement_premier_resultat () {
afficher_MSG "recherche_puis_lancement_premier_resultat"
on_cherche "$@"
$(wc -l < $fResultats) -eq ] || on_affiche_ou_lance_resultats "LANCER"
}
   
recherche_puis_lancement_premier_resultat_dossier () {
afficher_MSG "recherche_puis_lancement_premier_resultat_DOSSIER"
lancerDIR="TRUE"
on_cherche "$@"
$(wc -l < $fResultats) -eq ] || on_affiche_ou_lance_resultats "LANCER"
}
   
lancer_rechercheA () {
afficher_MSG "lancer_rechercheA sur : $*"
on_cherche "$*"
on_affiche_ou_lance_resultats
}

recherche_gnome_search_tool () {
afficher_MSG "recherche_gnome_search_tool"
gnome-search-tool --path=$SEARCHDIR --start --sortby=date  --named=$1
}

interactif () {
defaut="Entrez votre ligne de commande ici"
finter=${S3F_TMP}/s3f_interactif.interactif
if -f $finter ] ; then
 defaut="$(cat $finter)"
fi
r="$(zenity --entry --title "s3f en mode interactif" --text "Veuillez taper votre ligne de commande" --entry-text="$defaut")"
if "x$r" "x" ] ; then
 echo "Recherche abandonnée"
 return 0
fi
echo "$r" $finter
$0 "$r"
}

afficher_MSG () {
echo "$@"
}

if [ ! -d $DIR_CATALOGS ]; then
    echo "Le dossier $DIR_CATALOGS est absent."
else
    which updatedb || echo Installation de locate nécessaire
    which updatedb || sudo apt install locate
    rm -rf /tmp/s3f     # nettoyage d'une ancienne commande s3f
    mkdir /tmp/s3f
    ligne_commande "$@"
fi