# \[fgp\] : outil de recherche contenu fichiers, à récursivité adaptative

**URL:** <https://www.debian-fr.org/t/fgp-outil-de-recherche-contenu-fichiers-a-recursivite-adaptative/90489>\
**Category:** Trucs et Astuces\
**Created:** [Octobre 25, 2024, 8:19 UTC](https://www.debian-fr.org/t/fgp-outil-de-recherche-contenu-fichiers-a-recursivite-adaptative/90489 "2024-10-25T20:19:55Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Verner](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/v/34f0e0/32.png) [@Verner](https://www.debian-fr.org/u/Verner)\
**Post date:** [Octobre 25, 2024, 8:19 UTC](https://www.debian-fr.org/t/fgp-outil-de-recherche-contenu-fichiers-a-recursivite-adaptative/90489/1 "2024-10-25T20:19:55Z")

</div>

**Observations sur grep**  
grep est ou outil de recherche bien optionné, sous-exploité lorsqu’utilisé sporadiquement, qui a l’avantage d’être disponible par défaut, mais qui présente certains inconvénients:  
● sa récursivité est non maîtrisable; -r est juste binaire, ce qui est problématique dans de nombreux cas;  
● la sortie non formatée par défaut des résultats rend difficile l’exploitation des recherches lorsque le nombre de fichiers est élevé;  
● ses options par défaut ne sont pas les plus judicieuces en usage courant;  
En résumé, grep n’est pas adapté en usage terminal pour une recherche avancée dans une arborescence de répertoires.

Il existe de nombreuses solutions de recherche de contenu, mais n’en trouvant aucune répondant à mes critères d’usage courant, **fgp** est né (fgp = contraction de **f** ind + **g** re **p** ).

**fgp, c’est quoi ?**  
C’est un outil de recherche de contenu fichiers à récursivité adaptative s’appuyant sur find et grep, pour usage terminal, offrant une sortie conviviale des résultats.  
Son usage reste simple, intuitif, en limitant l’accès aux options essentielles et courantes.  
/!\ → non adapté pour usage dans un script.

**Pourquoi une récursivité adaptative ?**  
Parce-que généralement, lorsqu’on choisit un répertoire initial de recherche, on est en priorité plus intéressé par ce qui sera trouvé aux niveaux 1,2,3 qu’au niveau 15 de sous-répertoires.

**Usage:**  
`$ fgp <options> <regex Etendu> <fichier ou rep> <fichier ou rep> ...`

**Options par défaut:**  
● recherche à partir du répertoire courant, si aucun répertoire indiqué;  
● récursivité automatique (max 10) jusqu’aux premiers résultats, ou niveau max imposé par option ‹&nbsp;-N&nbsp;›  
● regex Etendu ; ex: ‹&nbsp;(abc|xyz)&nbsp;›  
● Masjucules/minuscules indifférenciées (inversable avec -ni)  
● ne traverse pas les systèmes de fichiers différents  
● exclusion des répertoires/fichiers cachés  
● exclusion des répertoires .cache, Trash, lost+found, et fichiers binaires  
● exclusion des fichiers non autorisés  
● avertissement au delà de 100 fichiers trouvés  
● extraction partielle ligne pour les très longues lignes, pour ne pas saturer l’affichage  
● affichage du temps de recherche (si \> 1 sec)  
● détection des variables commençant par un tiret

**Options:**

```plaintext
 -N : profondeur max N de recherche répertoires
 -r : récursivité (max 10)
 -mN : affichage limité aux N premières lignes trouvées par fichier (ex: -m2)
 -a,--all : recherche aussi dans les fichiers cachés
 -l,--files-with-matches : seul le nom du fichier sera affiché
 -ni,--no-ignore-case : distinction minuscule ou Majuscule
 -w,--word : recherche du mot cat -> 'xx/cat,yy' sera trouvé, mais pas 'xxcatyy'
 -v,--invert-match : recherche inversée
 -AN : affiche N lignes suivantes (After ; seulement pour entrée | )
 -q,--quiet : sortie muette, test uniquement (seulement pour entrée | )
 -nc,--no-color : suppression sortie couleur
 -h,--help : affiche cette aide

```

Le plus simple pour estimer si **fgp** présente un intérêt relativement à grep est de comparer à ce que trouve grep.  
Ouvrir un terminal pour fgp, et un autre pour grep, et comparer commande par commande:

```auto
fgp '^[decus]' /etc/apt/s{,*/}*[st]
fgp -a 'firefox'
fgp '(modules=|blacklist)' /etc/ /usr/share/
fgp '^P.*(esr|rbird)$' /var/
fgp -v '^(#|$)' /etc/dpkg/*.cfg
lspci -v | fgp -A7 audio
man cp | fgp '-deref' 

```

**fgp** :

```auto
#!/usr/bin/bash
# 20241109 ~ @verner
# fgp : outil de recherche contenu fichiers, à récursivité adaptative
# ――――――――
_help() { cat <<EOF | \
 sed '/^ -/s/[^:]*/\x1b[38;5;123m &\x1b[m/;s/fgp/\x1b[38;5;120m&\x1b[m/g'
 Usage: $ fgp <options> <regex E> <fichier ou rep> <fichier ou rep> ...

 Description:
  Recherche contenu fichiers à récursivité adaptative et sortie formatée.
  La liste d'options accessibles est limitée aux courantes (90% des besoins)

 Options par défaut:
  * recherche à partir du répertoire courant, si aucun répertoire indiqué;
  * récursivité automatique (max 10) jusqu'aux premiers résultats,
    ou niveau max imposé par option '-N'
  * regex Etendu ; ex: '(abc|xyz)'
  * Masjucules/minuscules indifférenciées (inversable avec -ni)
  * ne traverse pas les systèmes de fichiers différents
  * exclusion des répertoires/fichiers cachés
  * exclusion des répertoires .cache, Trash, lost+found, et fichiers binaires
  * exclusion des fichiers non autorisés
  * avertissement au delà de 100 fichiers trouvés
  * détection des variables commençant par un tiret

 Options:
 -a,--all : recherche aussi dans les répertoires/fichiers cachés
 -N : profondeur max N de recherche répertoires
 -r : récursivité (max 10)
 -mN : affichage limité aux N premières lignes trouvées par fichier (ex: -m2)
 -l,--files-with-matches : seul le nom du fichier sera affiché
 -w,--word : recherche de 'cat' -> 'xx/cat,yy' sera trouvé, mais pas 'xxcatyy'
 -v,--invert-match : recherche inversée
 -AN : affiche N lignes suivantes (After ; seulement pour entrée | )
 -q,--quiet : sortie muette, test uniquement (seulement pour entrée | )
 -ni,--no-ignore-case : distinction minuscule ou Majuscule
 -nc,--no-color : suppression sortie couleur
 -h,--help : affiche cette aide

 Exemples:
  fgp '^[scude]' /etc/apt/s{,*/}*[st]
  fgp -a 'firefox'
  fgp '(modules=|blacklist)' /etc /usr/share
  fgp '^P.*(esr|rbird)$' /var/
  fgp -v '^(#|$)' /etc/dpkg/*.cfg
  lspci -v | fgp 'audio' -A7
  man cp | fgp '-deref'
EOF
}
# ―――――――――
opt=EIhis
for x ; do
  case $x in
	-a|--all) a=1 ;; # + hiddens
	-l|--files-with-matches) l=-l ;; # print file-name only
	-w|--word) opt=w$opt ;; # exact word (more restrictive)
	-m*) ((${x/-m/}>0)) && mc=$x ;; # max count output
   -ni|--no-ignore-case) opt=${opt/i/} ;; # strict case
	-A*) ((${x/-A/}>0)) && A=$x ;; # After (pipe input only)
	-v|--invert-match) v=-v ;;
	-q|--quiet) q=-q ;;
   -nc|--no-color) cl=never ;;
	-r) md=10 ;;
	-h|--help) _help ; exit ;;
	-[0-9]*) ((${x/-/}>0)) 2>/dev/null && md=${x/-/} ;; # depth
	*) [-d "$x"] && R+=("$x") ||
	 { [-f "$x"] && F+=("$x") || pat="$x" ;} ;;
  esac
done
# ―――――――――
["$pat"] || { echo " > argument absent" ; exit 1 ;}
["$F$R"] || R=.
t0=$(date "+%s")
# ―――――――――
["$cl"] || { cl=always; GREP_COLORS='ms=01;36'; p='\x1b[38;5'; c0='\x1b[0m'
			cb="$p;75m";cc="$p;123m";cg="$p;120m";co="$p;215m";cy="$p;228m"; }
# ――――――――
if [-p /dev/stdin] ; then
	cat /dev/stdin | grep -$opt $v $q $mc $A --color=$cl -- "$pat" ; exit
fi
# ――――――――
p1="${pat/^/^[0-9]*:}" ; grep -q '\[' <<<"$pat" && p2=¤ || p2="${pat/^/}"
_gp() { grep -n$opt $mc -- "$pat" "$f" |sed 's#\(.\{120\}\)#\1\n#g' | \
	sed -rn "\%$p1%I{s/^[0-9]*:/${cy}& $c0/;s,$p2,${cc}&$c0,gI;p}"
	echo ; }
# ―――――――――
if ["$F"] ; then
  if ["$v"] ; then grep -ETvn $l --color=$cl -- "$pat" "${F[@]}"
    else while read f ; do sed "s,[^/]*$,${cg}&$c0," <<<"$f"
		  ["$l"] || _gp
		 done< <(grep -l -$opt -- "$pat" "${F[@]}")
  fi
fi

if ["$R"] ; then fmax=100; D=1
   ["$v"] && echo " > -v non compatible argument répertoire" && exit 1

msg1() { printf "――――\n» $lim$co$z$c0 fichiers sous "
	printf "$cb$(echo "${R[@]}")$c0 | depth: $co$D$c0 "
	T=$(($(date "+%s")-$t0))
	if (($T>1)) ; then S=$((T%60))s ; M=$(((T%3600)/60))mn
	   (($T<60)) && printf "| ~ $S" || printf "| ~ $M $S"
	fi
	echo ; }

   { ["$a"] || [[${R/\/.//} != $R]] ;} && hd='/¤' || hd='.*/\..*'

  for Rx in "${R[@]}" ; do d=1 ; y=0 ; ["$md"] && M=$md || M=1
   while ((d<=M)) ; do ex=1
	while read f ; do
	  if ((d>1)) && ["$ex"] ; then ex= ; ((M>D)) && D=$M
	   printf "${co}%0.s../" $(seq 1 $((d-1))) ; printf " $d ${c0}\n"
	  fi
	  sed "s,$Rx,${cb}&$c0,;s,[^/]*$,${cg}&$c0," <<<"$f"
	  ((y++)) ; ((z++))
	  ["$l"] || _gp
	  # ~~~~~~~~~~~
	  if ((z>=fmax)) ; then lim='Plus de ' ; msg1
		read -t 15 -p "On continue ? [o,y / n] " q </dev/tty
		[[$q == [oOyY]* ]] && fmax=$((fmax+100)) || { echo ; exit; }
	  fi
	  # ~~~~~~~~~~~
  	done< <(find "$Rx" -mount -follow -mindepth $d -maxdepth $d \
		\( -regex "${hd}\|\.cache\|Trash\|lost\+found\|recent" \
		   -o ! -readable -prune \) -o -type f -print0 2>/dev/null | \
		    xargs -0 grep -l -$opt -- "$pat" |LC_ALL=C sort -V)

    ((z>20)) && l=-l
    [-z "$md"] && ((y<10)) && ((M<10)) && ((M++))
    ((d++))
   done
  done
  if ((z==0)); then printf "${cy}» Rien trouvé / Options possibles:\n"
	    ["$a"] || printf " * recherche dans les fichiers cachés: -a\n"
					printf " * modifier le répertoire de recherche ${c0}\n"
					exit 1
 elif ((z>3)); then msg1
  fi
fi
# ―――――――――
exit

```

Exemples de sortie (partielle):

 ![2024-10-25_21-51](https://www.debian-fr.org/uploads/default/original/2X/a/a10fe5428b247a7a1cfb32b335d3a0732e9d0a50.jpeg)

 ![2024-10-25_2](https://www.debian-fr.org/uploads/default/original/2X/d/d2d37598f1292b5770805db1614b74c94ccd21ff.jpeg)

* * *

► Afin de garder ce sujet exploitable et de prévenir d’éventuels débordements hors-sujet,  
tout commentaire/question doit être abordé dans le sujet dédié: → [Observations sur fgp](https://www.debian-fr.org/t/observations-sur-fgp/90522)

* * *

---

<div class="post-metadata">

**Author:** ![Clochette](https://www.debian-fr.org/user_avatar/www.debian-fr.org/clochette/32/8757_2.png) [@Clochette](https://www.debian-fr.org/u/Clochette)\
**Post date:** [Novembre 5, 2024, 7:51 UTC](https://www.debian-fr.org/t/fgp-outil-de-recherche-contenu-fichiers-a-recursivite-adaptative/90489/2 "2024-11-05T07:51:46Z")

</div>

A scindé ce sujet (le Novembre 5, 2024, 7:51 UTC)

4 messages ont été scindés en un nouveau sujet : [**Observations sur fgp** P](https://www.debian-fr.org/t/observations-sur-fgp/90522)

---

<div class="post-metadata">

**Author:** ![Verner](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/v/34f0e0/32.png) [@Verner](https://www.debian-fr.org/u/Verner)\
**Post date:** [Novembre 8, 2024, 8:43 UTC](https://www.debian-fr.org/t/fgp-outil-de-recherche-contenu-fichiers-a-recursivite-adaptative/90489/3 "2024-11-08T20:43:11Z")

</div>

Changelog 2024 **1109**

- ajout de l’option `-q,--quiet`  
Bien que rarement utilisée en terminal, mais très fréquemment en script pour tester une variable sans afficher le résultat, cette option pourrait potentiellement être demandée plus tard (anticipation);

- fgp traite normalement une variable commençant par un tiret (piège classique de grep rencontré dans [ce sujet](https://www.debian-fr.org/t/test-sur-comparaison-de-variable-en-erreur-anormalement/90511/9) .

exemples:

```plaintext
man cp | grep '-deref'
   grep: argument « eref » incorrect pour « --directories »

```

```plaintext
man cp | fgp '-deref'
       -d same as --no-dereference --preserve=links
       -L, --dereference
       -P, --no-dereference

```

→ fgp: [fgp\_20241109.txt](https://www.debian-fr.org/uploads/short-url/vBuGwcqRfh3CECnSu86452q6p5.txt) (5,2 Ko)
