faire un tri par type de fichier ?

Rollmops

Membre expert
Club iGen
17 Juillet 2006
1 763
54
Bonjour à tous :)


Je voudrais trier par type de fichiers ( directory, Microsoft Office Document, data, Adobe Photoshop Image etc) ce résultat :

m237:~/Documents/Docus/DOCUMENTS/documents Rollmops$ file *
Installer Temp: directory
Installer Temp1: directory
**** essai : modèle plan: Microsoft Office Document
ALPHA-: directory
ARRCO: directory
Apple Extras: directory
AppleCDROM: empty
Applications: directory
Assistants: directory
B & E: directory
BEGHIN: directory
Bibliothèque audio: TrueType font data
CLIENTS AGENCE * (Convert cop(C: TrueType font data
lettre Mylene: data
rapport de stage: Microsoft Office Document
.../...

Je sais que la commande de tri est "sort" mais comment l'aménage-t-on pour qu'elle puisse faire ce genre de tri ? :confused:

Merci d'avance et bonne journée ;)
 
Déjà : tu n'es pas obligé de mettre tout ton listing ... :D

Tu pourras faire cela avec un peu de script malin. Genre : en PERL, en Python, en Ruby. Tous trois disponibles sur ton Mac (joie ! allégresse ! tout est là !)
Genre : tu charges dans un tableau, tu tries, tu ressors le tableau.

Tu peux aussi regarder avec awk, moins complexe donc plus accessible : pour chaque ligne, il faut mettre le type du fichier devant le nom du fichier. Puis un pipe vers sort et hop !
 
Merci bompi ;)

Pourrais-tu me donner un exemple concret pour le tri par type de fichier par awk (l'autre

solution par script me semble un peu pointue pour l'instant...) car ton explication est un

peu hermétique pour moi ( je suis vraiment très junior sur Unix).

J'ai regardé sur des tutos sur le net et n'ai pas trouvé grand chose là-dessus.

Merci
 
Voici un essai un brin rustique :
Bloc de code:
file * | awk '{ split ($0, a, ":"); gsub(/^[ \t]+/, "", a[2]); gsub(/[ \t]+$/, "", a[1]); print a[2] ":" a[1] }' | sort
C'est pas joli mais ça ressemble à ce que tu cherches à faire.
 
Génial ! Merci. ;) Ça marche.

Mais...euh...pourrais-tu un peu commenter cette syntaxe un peu complexe ?
 
Bien.
Il y a trois commandes qui s'enchaînent, connectées par des pipes (tuyaux), caractère '|', qui transmettent la sortie d'une commande à l'entrée de la suivante. Une des caractéristiques du monde UN*X, ça : on s'occupe de flux de données et c'est bien pratique.

La première commande est :
Bloc de code:
file *
qui applique la commande file, laquelle détermine le type d'un fichier en se basant grosso modo sur ses premiers caractères, à l'ensemble des fichiers présents dans le répertoire courant.

La deuxième commande est une commande awk (décrite ci-après) qui permet de travailler sur chaque ligne du flux de données entrant et de restituer une ligne formatée comme on le souhaite en sortie.

Enfin, la troisième commande :
Bloc de code:
sort
ordonne le flux entrant par ordre alphanumérique et le passe au shell qui l'affiche bien gentiment.

re-Bien.

Maintenant on s'occupe de la commande awk. Si je l'avais mise dans un fichier (ce qui est tout à fait possible), je l'aurais formattée de cette manière, bien plus lisible :
Bloc de code:
{
    split ($0, a, ":");
    gsub(/^[ \t]+/, "", a[2]);
    gsub(/[ \t]+$/, "", a[1]);
    print a[2] " : " a[1];
}
La première partie
Bloc de code:
split ($0, a, ":");
coupe la ligne (entière) en prenant comme séparateur la chaîne de caractères ":" et met tous les éléments dans un tableau, 'a'.
Comme une ligne produite par file est du genre :
Bloc de code:
out_file.xml:                   ASCII text
ce que tu veux avoir est le deuxième élément du tableau en premier, puis le premier élément du tableau.
Pour que ce soit moins moche, je vire les espaces (et tabulations) au début de la partie que je vais placer à gauche avec
Bloc de code:
gsub(/^[ \t]+/, "", a[2]);
ainsi que les espaces en fin de la partie que je vais placer à droite avec
Bloc de code:
gsub(/[ \t]+$/, "", a[1]);
Enfin, pour chaque ligne, je ressors les éléments dans l'ordre voulu avec
Bloc de code:
print a[2] " : " a[1];
Voili.
 
  • J’aime
Réactions: yzykom
Un grand bravo et un grand merci bompi pour cette superbe démonstration, c'est vraiment grâce à des gens comme toi qu'on apprend ! ;)
 
comme ça m'amusait de tout faire un bash, j'ai ça aussi....

file * | tr -s ' ' | sort -t ":" +1


le file *
liste
le tr -s ' '
supprime les espaces de début de colone qui empeche de bien trier les éléments
le sort -t ":"
reprend le délimiteur de chaine : enter le nom du fichier et le type
le +1
indique qu'il faut trier sur la deuxième colonne

:D

voili voilou... mais ça commence a tourner a l'usine a gaz quand meme :D
 
  • J’aime
Réactions: bompi
C'est bien :up: : c'est tout simple et ça fait ce que l'on veut.

Le scripting, c'est fun ;)
 
  • J’aime
Réactions: p4bl0
C'est bien :up: : c'est tout simple et ça fait ce que l'on veut.

Le scripting, c'est fun ;)

uste pour info, pour dire que sous nunux la scripting c'est mieux ....

file * | sort -t ":" -i -k 2

fonctionne parfaitement...
mais bon faut dire que sort --version : GNU coreutils 5.97 ça suffit....

et sous osx :
sort --version : sort - GNU textutils 1.14


beh oué faut pas trop rêver non plus....
 
Avec MacPorts, on peut installer facilement la version 5.96 ...
 
Merci canibal ;) pour ta solution mais je n'arrive pas à la faire fonctionner :

Si je tape ta commande :

file * | tr -s ' ' | sort -t ":" +1

après le répertoire concerné, ça ne marche pas...:eek:

j'obtiens "is a directory"...

m237:~ Rollmops$ /Users/Rollmops/Documents/Docus/DOCUMENTS/documents/ file * | tr -s ' ' | sort -t ":" +1
-bash: /Users/Rollmops/Documents/Docus/DOCUMENTS/documents/: is a directory
m237:~ Rollmops$

Où est le pb ? :confused:
 
Merci canibal ;) pour ta solution mais je n'arrive pas à la faire fonctionner :

Si je tape ta commande :

file * | tr -s ' ' | sort -t ":" +1

après le répertoire concerné, ça ne marche pas...:eek:

j'obtiens "is a directory"...

m237:~ Rollmops$ /Users/Rollmops/Documents/Docus/DOCUMENTS/documents/ file * | tr -s ' ' | sort -t ":" +1
-bash: /Users/Rollmops/Documents/Docus/DOCUMENTS/documents/: is a directory
m237:~ Rollmops$

Où est le pb ? :confused:

Essaye plutot :

file /Users/Rollmops/Documents/Docus/DOCUMENTS/documents/* | tr -s ' ' | sort -t ":" +1

ça devrait mieux marcher ;)
 
Merci :) j'ai essayé mais :

m237:~ Rollmops$ file /Users/Rollmops/Documents/Docus/DOCUMENTS/documents/* | tr -s ' ' | sort -t ":" +1
/Users/Rollmops/Documents/Docus/DOCUMENTS/documents/*: cannot open (/Users/Rollmops/Documents/Docus/DOCUMENTS/documents/*)
m237:~ Rollmops$
 
OK ! Tout fonctionne, excuse-moi, j'avais fait une erreur de transcription.:siffle:

Effectivement c'est un peu l'usine à gaz mais bon ça marche...et la commande est beaucoup plus simple.:)

Au fait, et ça n'a rien à voir : comment se fait-il que dans un cas comme dans l'autre (ta commande et celle de bompi) mes vieilles données texte Clarisworks se nomment "data" ?

Est-il impossible au shell de reconnaître des données texte aussi simples que Clarisworks alors qu'il reconnaît des données Word ? :confused:
 
Beh en fait, la commande file utilise l'analyse MIME pour reconnaitre un type de fichier.

Il scanne les premiers octets du fichier pour savoir a quel type de fichier il a affaire.

Si ton ftype de fichier n'a pas d'entete particulier, ou pas d'entete reconnu, il affichera simplement un fichier data.

Pour ce qui est de word.... l'entete du fichier est très très reconnaissable.... suffit de faire un more sur ton fichier pour l'ouvrir en mode texte... tu vas voir a quel point rien ne ressemble plus a un fichier word.... qu'un autre fichier word ;)
 
Merci ;)

J'ai essayé la commande "more" que je ne connaissais pas mais je n'arrive pas à la faire fonctionner. Peux-tu me dire où ça coince ? :confused:

J'ai essayé :

m237:~ Rollmops$ /Users/Rollmops/Documents/Docus/more LETTRE\ REDOUTE.doc

ça ne marche pas :

m237:~ Rollmops$ /Users/Rollmops/Documents/Docus/more LETTRE\ REDOUTE.doc
-bash: /Users/Rollmops/Documents/Docus/more: No such file or directory

et aussi :

m237:~ Rollmops$ more /Users/Rollmops/Documents/Docus/ LETTRE\ REDOUTE.doc

ça ne marche pas non plus :

m237:~ Rollmops$ more /Users/Rollmops/Documents/Docus/ LETTRE\ REDOUTE.doc
/Users/Rollmops/Documents/Docus/ is a directory
LETTRE REDOUTE.doc: No such file or directory
m237:~ Rollmops$
 
Merci ;)

J'ai essayé la commande "more" que je ne connaissais pas mais je n'arrive pas à la faire fonctionner. Peux-tu me dire où ça coince ? :confused:

J'ai essayé :

m237:~ Rollmops$ /Users/Rollmops/Documents/Docus/more LETTRE\ REDOUTE.doc

ça ne marche pas :

m237:~ Rollmops$ /Users/Rollmops/Documents/Docus/more LETTRE\ REDOUTE.doc
-bash: /Users/Rollmops/Documents/Docus/more: No such file or directory
Il y a deux erreurs:
  1. more (comme less) ne peut lire que des fichiers texte .txt, ou encore les scripts .sh, etc. (c'est-à-dire du texte pur);
  2. il aurait fallu mettre une espace entre le chemin du répertoire courant et la commande more.
et aussi :

m237:~ Rollmops$ more /Users/Rollmops/Documents/Docus/ LETTRE\ REDOUTE.doc

ça ne marche pas non plus :

m237:~ Rollmops$ more /Users/Rollmops/Documents/Docus/ LETTRE\ REDOUTE.doc
/Users/Rollmops/Documents/Docus/ is a directory
LETTRE REDOUTE.doc: No such file or directory
m237:~ Rollmops$
Là, c'est l'espace entre "Docus/" et "LETTRE\"
 
juste comme petit truc rapidos....pour la suite de ta petite vie dans le monde des lignes de commandes :

en bash, comme dans tous les scripts shell (même DOS ...si si je te jure), le principe c'est :

commande [option]
ou
commande [chemin]
dans ton cas

pour toute les commandes, tu dois commencer ta ligne par la commande :
que ce soit
file
more
tail
...

ce sont des mots clés, il en existe des tonnes tu peux les obtenirs en t'acharnant sur la commande tabulation dans le terminal, et en otenir un descriptif précis de ce a quoi elles servent (commande man.... d'ou le RTFM que tu peux retrouver sur certains sites très virulent a l'encontre des gens qui ne cherchent pas... "Read The Fu*** Manual")
Donc pour savoir comment fonctionne la commande more : tu fais man more
pour info c'est q pour quitter ;)

pour ce qui est de ton problème de chemin.... pense bien que sous le shell l'espace n'est pas très apprécié et chaques fois que tu le veux tu peux utiliser la complétion pour t'aider...

par exemple si tu tapes /User/m puis tabulation, il t'affichera gentiment l'ensemble des chemins possible...
/User/mince
/User/mercredi
/User/merci
etc

donc ton chemin doit toujours être spéaré par des / ... si tu vois un \ c'est qu'il s'ensuit un caractère spécial qui peut être interprété par le shell... comme l'espace par exemple...


J'espère que ça t'aideras un peu dans l'avancement des scripts shell....

Bonne continuation