Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 11/03/2021, à 13:49

Tawal

[Résolu] Lister les fichiers de type "text"

Hello,

Je cherche, pour manipulation dans un script, à lister tous les fichiers (d'un répertoire et/pas des sous répertoires) de type "text".

Pour l'instant, ma construction la plus sûre (sur les noms de fichiers) est celle là :

find "$Doss" -type f \! -empty -print0 | while IFS='' read -rd '' fich    # Liste et récupération du nom de fichier
do
    if file -b "$fich" | grep -q text         # Test du type du fichier
    then 
        echo "Fichier : $fich contient :" 
        cat "$fich"                            # Actions sur le fichier
    fi
done

Pour gérer la récursivité, il suffit de rajouter l'option -maxdepth 1 à find.
Ça fonctionne, mais c'est lent à mon goût. Ça résiste à pas mal de caractères spéciaux dans les noms de fichier.

Je me demande s'il ne serait pas possible d'intégrer le test file ... dans l'option -exec de find ?
Dans le genre :
find "$Doss" -type f \! -empty -exec file -b '{}' | grep -q text \; -print0
Mais je ne sais pas faire ni ne sais si c'est possible.

En vous remerciant de vos éclairages wink

PS : j'ai des commandes plus rapides, mais je perds la "solidité" des noms de fichiers.

Dernière modification par Tawal (Le 12/03/2021, à 20:25)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#2 Le 11/03/2021, à 14:15

Watael

Re : [Résolu] Lister les fichiers de type "text"

s'il n'est pas question de descendre dans les sous-répertoires, une simple boucle for ne suffirait-elle pas ?

for f in *
do
   if [[ $(file -b  "$f") == *text ]]
   then
      echo "$f"
      cat "$f"
   fi
done

?

Dernière modification par Watael (Le 11/03/2021, à 17:53)


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#3 Le 11/03/2021, à 14:49

Tawal

Re : [Résolu] Lister les fichiers de type "text"

J'avais pensé à ce type de boucle.
Mais la question de la récursivité (qui m'importe) m'a fait me diriger vers find.
Je veux pouvoir "jongler" entre récursivité ou pas.

Je prend note de l'écriture du test wink

Au plaisir.

PS: une petite faute de frappe sur ton cat


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#4 Le 11/03/2021, à 16:01

MicP

Re : [Résolu] Lister les fichiers de type "text"

Tawal a écrit :

…la question de la récursivité (qui m'importe) m'a fait me diriger vers find.…

Watael a démontré plusieurs fois sur ce forum qu'on pouvait aussi se passer de find dans ce cas là,
en utilisant une boucle for et les options relatives aux caractères et expressions génériques du shell

Si je me souviens bien,
ça donnerait, en enlevant le t qui est en trop après le cat (faute de frappe)
quelque chose comme çà :

shopt -s globstar nullglob
for f in **/*
do
   if [[ $(file -b  "$f") == *text ]]
   then
      echo "Fichier : \"$f\" contient :" 
      cat "$f"
   fi
done
shopt -u globstar nullglob

Dernière modification par MicP (Le 11/03/2021, à 16:26)

Hors ligne

#5 Le 11/03/2021, à 16:40

Tawal

Re : [Résolu] Lister les fichiers de type "text"

MicP a écrit :

Watael a démontré plusieurs fois sur ce forum qu'on pouvait aussi se passer de find dans ce cas là,
en utilisant une boucle for et les options relatives aux caractères et expressions génériques du shell

Sans aucun doute wink

Mais je voudrais pouvoir gérer la récursivité par une option passée au script (cf. Options Courtes et ....)

Donc dans le cas de la boucle proposée par Watael en #2, il faut encore parcourir l'arborescence si la récursivité est demandée.

Dans le cas de ta boucle (qui fonctionne très bien), je ne vois pas comment éviter la récursivité si elle n'est pas désirée.

Pour l'instant, j'ai un truc du genre :

while IFS='' read -r -d '' fich
do
    [[ $(file -b "$fich") =~ text ]] &&
    {
        Commandes sur "$fich" ...
        ...
    }
done < <(find "$Dossier" $option_recursivite -type f -print0)

En mettant option_rec à "-maxdepth 0", on bloque la récursivité de find.
En initialisant option_rec="" , on "libère" la récursivité de find.

Au plaisir.

Edit: Je suis intéressé par les boucles for, elles ont quasiment les même performances que celle avec find.

Dernière modification par Tawal (Le 11/03/2021, à 17:15)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#6 Le 11/03/2021, à 17:30

Tawal

Re : [Résolu] Lister les fichiers de type "text"

Peut-on faire ce genre de chose  ? (ça fonctionne) :

if [ $option_recursivite = "OK" ]
then
    glob="./**/*"
else
    glob="./*"
fi

cd "$Doss" || exit 1

shopt -s globstar nullglob
for fich in $glob
do
   if [[ $(file -b  "$fich") =~ text ]]
   then
      echo "Fichier : $fich"
   fi
done
shopt -u globstar nullglob

Edit: Changement des glob en "./*" et ./**/*"

Dernière modification par Tawal (Le 11/03/2021, à 17:35)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#7 Le 11/03/2021, à 18:31

MicP

Re : [Résolu] Lister les fichiers de type "text"

Tant qu'à faire,
autant faire une liste en fonction de la variable option_recursive
et fournir ensuite la liste toute faîte à la boucle for

Ce qui donnerait :

#!/bin/bash

option_recursive="vide ou n'importe quoi mais pas un 'Oui' tout seul"
# ou alors :
option_recursive="Oui"

shopt -s globstar nullglob
if test "$option_recursive" = "Oui"
then
    tblFichs=( ./**/* )
else
    tblFichs=( ./* )
fi
shopt -u globstar nullglob

for fich in "${tblFichs[@]}"
do
   if [[ $(file -b  "$fich") =~ text ]]
   then
      echo "Fichier : $fich"
   fi
done

Dernière modification par MicP (Le 11/03/2021, à 18:42)

Hors ligne

#8 Le 11/03/2021, à 18:39

Watael

Re : [Résolu] Lister les fichiers de type "text"

les options shopt ne nuisent pas; les désaffecter n'est pas indispensable.

...
shopt -s nullglob
if test "$option_recursive" = "Oui"
then
    shopt -s globstar #ça n'a de sens qu'ici
    tblFiles=( ./**/* )
else
    tblFiles=( ./* )
fi
#shopt -u globstar nullglob #les laisser, ou pas...

for fich in "${tblFiles[@]}"
do...

Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#9 Le 11/03/2021, à 18:47

MicP

Re : [Résolu] Lister les fichiers de type "text"

Merci beaucoup smile

Donc, il n'a que le nullglob qui est utile
et il n'est pas indispensable de le désactiver ensuite.

Dernière modification par MicP (Le 11/03/2021, à 18:49)

Hors ligne

#10 Le 11/03/2021, à 19:14

Tawal

Re : [Résolu] Lister les fichiers de type "text"

@MicP : Quel est l'avantage de passer par un tableau ?
À part le fait de pouvoir réutiliser la liste plus tard.

Ensuite, par rapport à find ... | while ... , il faut modifier les globs pour qu'ils prennent en compte les dossiers et fichiers cachés (commençant par un .). Je ne les ai pas de mémoire, mais ça se retrouve.

@Watael : Merci pour les précisions sur shopt wink

Edit: pour avoir les fichiers et dossier masqués il suffit de passer l'option dotglob à shopt, on a donc :
shopt -s nullglob globstar dotglob

Dernière modification par Tawal (Le 11/03/2021, à 20:16)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#11 Le 12/03/2021, à 17:22

Tawal

Re : [Résolu] Lister les fichiers de type "text"

Hello,

Tout d'abord, je viens dire que j'ai adopté la méthode avec la boucle for et les globs (c'est tout built-in).
Donc merci à vous Watael et MicP.

J'ai quand même cherché à intégrer le test dans la commande find, et j'ai trouvé une méthode (bonne ou pas, elle fonctionne), du coup :
J'ai fait un "test" de performance avec time, comparant la boucle for in "glob" ... et find ... -exec ....
Les deux réalisant le même travail.

Commande find  ... -exec ... :

$ time find /home/tawal -type f -exec bash -c '[[ $(file -b "$1") =~ text ]] && grep -H tawal "$1"' sh '{}' \;
...
...
real	21m9,488s
user	7m24,375s
sys	7m19,708s
$

Boucle for ...

$ shopt -s globstar nullglob dotglob
$ time for fich in /home/tawal/**/*; do if [[ $(file -b  "$fich") =~ text ]]; then grep -H tawal "$fich"; fi; done
...
...
real	21m55,282s
user	6m18,681s
sys	10m38,135s
$

Il y a une petite différence (que je considère négligeable).
Et ça renforce mon choix vers la boucle for.

Encore merci wink

Dernière modification par Tawal (Le 12/03/2021, à 18:15)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#12 Le 13/03/2021, à 02:08

kamaris

Re : [Résolu] Lister les fichiers de type "text"

Un truc comme ça devrait être bien plus rapide sur du gros volume (pas testé) :

find /home/tawal -type f -exec file -0 {} + | awk -F: '/text/{printf $1}' | xargs -0 grep -H tawal

Hors ligne

#13 Le 13/03/2021, à 09:48

Tawal

Re : [Résolu] Lister les fichiers de type "text"

Oui, certainement, c'est ce que j'avais constaté (cf. #1)

Mais le awk -F: '/text/{printf $1}' casse la solidité des noms de fichiers :

  • Certains caractères de nom de fichier passent mal

  • Le séparateur ":" pose problème : il peut être présent dans un nom de fichier et donc awk coupe le nom en 2.

Non, je reste sur la boucle for

Dans mon cas, find ne sert qu'à lister les fichiers (pas de tri particulier).
Donc les boucles for i in ./*; do ...    et    for i in ./**/*; do ...  sont aussi performantes que find (en temps réel).
Si la sélection des fichiers devait être plus fine et dans des répertoires isolés les uns des autres, find serait vraiment utile.

Merci à toi.

Au plaisir.

Dernière modification par Tawal (Le 13/03/2021, à 10:32)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#14 Le 13/03/2021, à 14:21

kamaris

Re : [Résolu] Lister les fichiers de type "text"

L'enjeu n'est pas tellement la recherche par find, mais le fait de ne pas briser la chaine des flux.
Quand on le peut, sur de gros volumes, il ne faut pas travailler en séquentiel en lançant une commande par fichier, mais travailler en parallèle en lançant une commande pour autant de fichiers que possible.
C'est ce que permet la formulation avec les pipes : il sont exécutés en parallèle, et le flux sortant de find est préservé jusqu'au grep final.

Quant au problème des noms de fichiers, un petit travail dans awk permet de le régler (en modifiant aussi un peu l'option de formatage de file):

find /home/tawal -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{files[n++]=file} END{for (i=0;i<n;i++) printf("%s\0",files[i])}' | xargs -0 grep -H tawal

Hors ligne

#15 Le 13/03/2021, à 14:42

beuguissime

Re : [Résolu] Lister les fichiers de type "text"

Salut,

Tawal a écrit :

Mais le awk -F: '/text/{printf $1}' casse la solidité des noms de fichiers :

  • Certains caractères de nom de fichier passent mal

Peux-tu donner un exemple stp ?

Hors ligne

#16 Le 13/03/2021, à 16:32

Tawal

Re : [Résolu] Lister les fichiers de type "text"

En voilà plusieurs d'un coup :

$ ls -l
total 216
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\377'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\300\200'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\377\377\377\377'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\177'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\n'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\n\n'
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 ' '
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 '  '
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '!!'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '"'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 "'"
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '*'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  -
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  --
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '\'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '\\'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '{} [] | " "'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '~'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '` ! @ # $ % ^ & * ( ) _ - + ~ ='
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '!-1'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\033''[5;34;42mIn color'$'\033''[0;37;40mNot in color'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\360\244''BAD'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  --force
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  -n
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '\n'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '-n --force'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 'not-control-\ty'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 'Q'$'\177'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '~root'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\001''x'$'\001''y'$'\001'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\n''x'$'\n''y'$'\n'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\n''x'$'\n''y'$'\n\n'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\n''x'$'\n''y'$'\n\r'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\n''x'$'\n''y'$'\r\n'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 ''$'\r''x'$'\r''y'$'\r'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 'x'$'\t''y'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 'x'$'\n''y'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 'xy[az]'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  xyz
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 '  xyz  '
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '(xyz)'
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 'x  y z'
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 'x y z'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  x{yz}
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58  xyz
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 'xyz '
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58 'xyz  '
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58  ZZ
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '. '
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '.. '
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '; : < > , . ?'
-rw-r--r-- 1 tawal tawal 3 mars  12 15:58 '.a bc'
-rw-r--r-- 1 tawal tawal 2 mars  12 15:58  .abc
$
$
$ find -type f | awk '{print "Fichier : "$1}'
Fichier : ./`
Fichier : ./(xyz)
Fichier : ./-n
Fichier : ./xyz
Fichier : ./"
Fichier : ./.abc
Fichier : ./
Fichier : ./
Fichier : x
Fichier : y
Fichier : 
Fichier : 
Fichier : ./x
Fichier : ./
Fichier : ./x
Fichier : ./~root
Fichier : ./x
Fichier : y
Fichier : ./\n
Fichier : ./~
Fichier : ./
Fichier : ./
Fichier : x
Fichier : y
Fichier : 
Fichier : ./.
Fichier : ./
Fichier : ./
Fichier : ./Q
Fichier : ./-
Fichier : ./\\
Fichier : ./!-1
Fichier : ./..
Fichier : ./;
Fichier : ./
Fichier : x
Fichier : y
Fichier : 
Fichier : ./ZZ
Fichier : ./xyz
Fichier : ./--
Fichier : ./xy
Fichier : ./
Fichier : 
Fichier : ./.a
Fichier : ./BAD
Fichier : ./
Fichier : 
Fichier : 
Fichier : ./In
Fichier : ./\
Fichier : ./xyz
Fichier : ./not-control-\ty
Fichier : ./--force
Fichier : ./
Fichier : ./
Fichier : x
Fichier : y
Fichier : 
Fichier : ./x{yz}
Fichier : ./
Fichier : ./-n
Fichier : ./
yichier : ./
Fichier : ./!!
Fichier : ./'
Fichier : ./xy[az]
Fichier : ./xyz
Fichier : ./*
Fichier : ./{}
Fichier : ./x
$

On voit quelque ratés.

Dans le même dossier avec le fichier t(retour ligne)t en plus

$ find -type f | awk '{print $1}' | xargs rm
rm: impossible de supprimer './`': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './-n': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './xyz': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer 'x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer 'y': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer 'y': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer 'x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer 'y': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './.': est un dossier
rm: impossible de supprimer './..': est un dossier
rm: impossible de supprimer './;': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer 'x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer 'y': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer './.a': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer './'$'\033''[5;34;42mIn': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer 'x': Aucun fichier ou dossier de ce type
rm: impossible de supprimer 'y'$'\r': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer './': est un dossier
rm: impossible de supprimer './t': Aucun fichier ou dossier de ce type
rm: impossible de supprimer 't': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './xyz': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './{}': Aucun fichier ou dossier de ce type
rm: impossible de supprimer './x': Aucun fichier ou dossier de ce type
$

Exemple sur un seul fichier :

$ touch "t
> "
$ ll
total 0
-rw-r--r-- 1 tawal tawal 0 mars  13 16:57 't'$'\n'
$ echo "TTTT" > "t
> "
$ cat "t
> "
TTTT
$ find -type f -exec file -0 '{}' \;
./t
: ASCII text
$ find -type f -exec file -b '{}' \; | awk -F: '$2 ~ /text/ {print $1}'
$
$ for i in ./*; do echo "$i"; done
./t

$
$ find -type f  | awk '{print $1}'
./t

$ find -type f  | awk '{print $1}' | xargs rm
rm: impossible de supprimer './t': Aucun fichier ou dossier de ce type
$ find -type f -print0 | awk '{print $1}' | xargs rm
rm: impossible de supprimer './t': Aucun fichier ou dossier de ce type
$ find -type f -print0 | xargs rm
xargs: ATTENTION : un caractère nul est arrivé en entrée. Il ne peut être ajouté à la liste d'arguments. Vouliez-vous en fait spécifier l'option --null ?
rm: impossible de supprimer './t': Aucun fichier ou dossier de ce type
rm: impossible de supprimer '': Aucun fichier ou dossier de ce type
$ find -type f -print0 | xargs -0 rm
$ ls -l
total 0
$

Dernière modification par Tawal (Le 13/03/2021, à 17:07)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#17 Le 13/03/2021, à 16:47

kamaris

Re : [Résolu] Lister les fichiers de type "text"

Oui, sauf que

find -type f | awk '{print "Fichier : "$1}'

est sensiblement différent de

find -type f -exec file -0 {} + | awk -F: '/text/{printf $1}'

Dans le second cas, les problèmes devraient à peu près être réduits aux cas où le nom de fichier contient : ou \n (ou text…).

Mais cela devrait de toutes façons être réglé dans la formulation que j'ai donnée en #14.
L'as-tu testée ? Pourrait-on avoir un comparatif des temps de calcul comme en #11 ?
Merci.

Hors ligne

#18 Le 13/03/2021, à 17:33

Tawal

Re : [Résolu] Lister les fichiers de type "text"

Re,

Désole kamaris, mais j'ai d'abord répondu à beuguissime.

Bizarrement, ta commande ne renvoie aucun retour !
Voici :

tawal@Deb1:~$ time find /home/tawal -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{files[n++]=file} END{for (i=0;i<n;i++) printf("%s\0",files[i])}' | xargs -0 grep -H tawal

real	10m38,144s
user	3m39,745s
sys	0m23,630s
tawal@Deb1:~$ echo ${PIPESTATUS[@]}
0 0 123
tawal@Deb1:~$

Par contre coté performance ... rien à dire wink

J'avais bien compris le souci du flux, mais ma méconnaissance d'awk ne me permet pas de le garder intact.
J'ai su déchiffrer ta formulation mais je serais incapable de la reproduire intuitivement.

Merci bien de ta clarté.

Edit: le format de flux serait-il encore brisé par awk ?

Edit2: Le code retour 123 concerne xargs et j'ai trouvé ceci :

123 means that at least one of xargs's invocations of grep returned a non-zero error code

Donc, au moins un nom de fichier est passé au travers je pense.

Edit3: En fait ton awk ne fonctionne pas :

tawal@Deb1:~/Term/evil-name/evil$ find -type f -exec file -00 {} +
./` ! @ # $ % ^ & * ( ) _ - + ~ =ASCII text./(xyz)ASCII text./-n --forceASCII text./xyz ASCII text./"ASCII text./.abcASCII text./ASCII text./
x
y

ASCII text./x y zASCII text./ASCII text./x  y zASCII text./~rootASCII text./x
yASCII text./\nASCII text./~ASCII text./ASCII text./
x
y
ASCII text./. ASCII text./ASCII text./ASCII text./QASCII text./-ASCII text./\\ASCII text./!-1ASCII text./.. ASCII text./; : < > , . ?ASCII text./
x
y
ASCII text./ZZASCII text./xyzASCII text./--ASCII text./xyASCII text./
ASCII text./.a bcASCII text./BADASCII text./

ASCII text./In colorNot in colorASCII text./\ASCII text./xyzASCII text./not-control-\tyASCII text./--forceASCII text./  xyz  ASCII text./
x
y
ASCII text./!!ASCII text./'ASCII text./xy[az]ASCII text./xyz  ASCII text./*ASCII text./{} [] | " "ASCII text./x yASCII texttawal@Deb1:~/Term/evil-name/evil$ 
tawal@Deb1:~/Term/evil-name/evil$ find -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{files[n++]=file} END{for (i=0;i<n;i++) printf("%s\0",files[i])}'
tawal@Deb1:~/Term/evil-name/evil$ echo ${PIPESTATUS[@]}
0 0
tawal@Deb1:~/Term/evil-name/evil$

Dernière modification par Tawal (Le 13/03/2021, à 17:54)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#19 Le 13/03/2021, à 18:32

kamaris

Re : [Résolu] Lister les fichiers de type "text"

Merci pour le retour smile
Je m'attendais à mieux pour tout dire, mais c'est déjà pas mal, et l'écart ne ferait que croitre (probablement non linéairement) par rapport aux autres méthodes avec la quantité de données.

C'est effectivement normal que xargs renvoie 123 si grep ne trouve rien, mais il devrait trouver quelque chose : le résultat devrait exactement le même qu'avec les autres méthodes.
Il y a probablement un peu de débogage à faire, mais l'erreur ne me saute pas aux yeux : il me faudrait ton cas de test pour bien faire, mais dans ce cas-là ça n'est pas évident…

Sinon pour le code awk, j'ai compliqué inutilement les choses. L'ensemble peut s'écrire comme ça :

find /home/tawal -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{printf("%s\0",file)}' | xargs -0 grep -H tawal

Peut-être est-ce d'ailleurs plus rapide, si awk commence à écrire plus vite dans le pipe…

EDIT: je n'avais pas vu ton cas de test ci-dessus dans l'Edit 3 : je regarde ça et je reviens.

Dernière modification par kamaris (Le 13/03/2021, à 18:34)

Hors ligne

#20 Le 13/03/2021, à 18:52

kamaris

Re : [Résolu] Lister les fichiers de type "text"

Je ne sais pas trop d'où peut venir le problème, car chez moi ça marche : si je prends simplement ton premier nom de fichier :

$ echo a >'` ! @ # $ % ^ & * ( ) _ - + ~ ='
$ find -type f -exec file -00 {} +
./` ! @ # $ % ^ & * ( ) _ - + ~ =ASCII text$ 
$ find -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{files[n++]=file} END{for (i=0;i<n;i++) printf("%s\0",files[i])}'
./` ! @ # $ % ^ & * ( ) _ - + ~ =$ 
$ find -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{printf("%s\0",file)}'
./` ! @ # $ % ^ & * ( ) _ - + ~ =$ 
$ 

Peut-être une question de version de awk ? Je n'ai pas l'impression qu'il y ait des choses spécifiques à gawk dans ce code, mais peut-être forcer l'utilisation de gawk ?

Hors ligne

#21 Le 13/03/2021, à 19:15

kamaris

Re : [Résolu] Lister les fichiers de type "text"

Autre essai : si ça ne marche pas avec awk, ça marchera peut-être avec sed ! big_smile

find /home/tawal -type f -exec file -00 {} + | sed -nz '1~2{h;n}; /text/{g;p}' | xargs -0 grep -H tawal

Rq : l'option -z de sed est une extension GNU.

Dernière modification par kamaris (Le 13/03/2021, à 19:19)

Hors ligne

#22 Le 13/03/2021, à 19:53

Tawal

Re : [Résolu] Lister les fichiers de type "text"

Pourquoi se compliquer la vie, alors que la simple boucle for avec les bons globs suffit pour mon cas.

Pour les noms de fichiers du #16, certains caractères sont invisibles mais présents dans le nom.
Il y a des noms simples avec des caractères affichables et d'autres plus compliqués avec des retours chariots, retour ligne etc ...

Au plaisir.


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#23 Le 13/03/2021, à 20:03

kamaris

Re : [Résolu] Lister les fichiers de type "text"

Ok, ok, j'arrête là, mais je persiste et signe : la boucle for (ou toute autre méthode séquentielle) n'est pas la bonne méthode dans ce cas.
Pour ce qui est des noms de fichiers du #16, aucun ne devrait poser problème : les délimiteurs sont des caractères nuls.
Il y a donc un autre problème que je ne m'explique pas, tant pis hmm

Hors ligne

#24 Le 13/03/2021, à 20:55

Tawal

Re : [Résolu] Lister les fichiers de type "text"

kamaris a écrit :

la boucle for (ou toute autre méthode séquentielle) n'est pas la bonne méthode dans ce cas.

Oui pour un gros travail (beaucoup de fichier et dossier).
Mais mon cas d'application est plus simple et plus léger à traiter.
Donc je reste sur la boucle for.


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#25 Le 10/04/2021, à 19:00

Tawal

Re : [Résolu] Lister les fichiers de type "text"

Hello,

Un petit retour.

@kamaris :
Le problème d'aucun retour de ta commande du #19 chez moi venait de spécificité gwak. (c'est toi qui en parlait au #20)
En effet, depuis qu'il est installé, ta commande renvoie bien un retour smile
du coup, j'ai refait le test de performance :

$ time find /home/tawal -type f -exec file -00 {} + | awk 'BEGIN{RS="\0"} (NR % 2 == 1){file=$0; next} /text/{printf("%s\0",file)}' | xargs -0 grep -H tawal
...
real	11m57,594s
user	4m54,774s
sys	0m27,809s
$

On reste dans les même temps que sans retour (voir #18), donc le temps est impacté à find.
(pas de retour awk = pas de xargs ni grep)

Vli,vlà,vloù c'était pour la compréhension wink smile

Dernière modification par Tawal (Le 10/04/2021, à 19:28)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne