#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
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
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"
…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"
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
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
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
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
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,
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
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
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 !
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
Hors ligne
#24 Le 13/03/2021, à 20:55
- Tawal
Re : [Résolu] Lister les fichiers de type "text"
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
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
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