# faire un tri par type de fichier ?



## Rollmops (13 Juin 2007)

Bonjour &#224; tous 


Je voudrais *trier par type de fichiers* ( directory, Microsoft Office Document, data, Adobe Photoshop Image etc) ce r&#233;sultat :

m237:~/Documents/Docus/DOCUMENTS/documents Rollmops$ file *
 Installer Temp:                 directory
 Installer Temp1:                directory
**** essai : mode&#768;le plan:          Microsoft Office Document
ALPHA-:                          directory
ARRCO:                           directory
Apple Extras:                    directory
AppleCDROM:                      empty
Applications:                    directory
Assistants:                      directory
B & E:                           directory
BEGHIN:                          directory
Bibliothe&#768;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 "*sor*t" mais comment l'am&#233;nage-t-on pour qu'elle puisse faire ce genre de tri ? 

Merci d'avance et bonne journ&#233;e


----------



## bompi (13 Juin 2007)

D&#233;j&#224; : tu n'es pas oblig&#233; de mettre _tout_ ton listing ... 

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&#233;gresse ! tout est l&#224; !)
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 !


----------



## Rollmops (13 Juin 2007)

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


----------



## bompi (13 Juin 2007)

Voici un essai un brin rustique :
	
	



```
file * | awk '{ split ($0, a, ":"); gsub(/^[ \t]+/, "", a[2]); gsub(/[ \t]+$/, "", a[1]); print a[2] ":" a[1] }' | sort
```
 C'est pas joli mais &#231;a ressemble &#224; ce que tu cherches &#224; faire.


----------



## Rollmops (13 Juin 2007)

Génial ! Merci.  Ça marche.

Mais...euh...pourrais-tu un peu commenter cette syntaxe un peu complexe ?


----------



## bompi (13 Juin 2007)

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 :
	
	



```
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 :
	
	



```
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 :
	
	



```
{
    split ($0, a, ":");
    gsub(/^[ \t]+/, "", a[2]);
    gsub(/[ \t]+$/, "", a[1]);
    print a[2] " : " a[1];
}
```
La première partie 
	
	



```
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 : 
	
	



```
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 
	
	



```
gsub(/^[ \t]+/, "", a[2]);
```
ainsi que les espaces en fin de la partie que je vais placer à droite avec
	
	



```
gsub(/[ \t]+$/, "", a[1]);
```
Enfin, pour chaque ligne, je ressors les éléments dans l'ordre voulu avec 
	
	



```
print a[2] " : " a[1];
```
Voili.


----------



## Rollmops (13 Juin 2007)

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 !


----------



## canibal (18 Juin 2007)

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



voili voilou... mais ça commence a tourner a l'usine a gaz quand meme


----------



## bompi (19 Juin 2007)

C'est bien  : c'est tout simple et &#231;a fait ce que l'on veut.

Le scripting, c'est _fun_


----------



## canibal (19 Juin 2007)

bompi a dit:


> C'est bien  : 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....


----------



## bompi (19 Juin 2007)

Avec MacPorts, on peut installer facilement la version 5.96 ...


----------



## Rollmops (20 Juin 2007)

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...

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 ?


----------



## canibal (20 Juin 2007)

Rollmops a dit:


> Merci canibal  pour ta solution mais je n'arrive pas à la faire fonctionner :
> 
> Si je tape ta commande :
> 
> ...



Essaye plutot :

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

ça devrait mieux marcher


----------



## Rollmops (20 Juin 2007)

Merci  j'ai essay&#233; 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$


----------



## canibal (20 Juin 2007)

et ls -al  */Users/Rollmops/Documents/Docus/DOCUMENTS/documents/

&#231;a te renvois quoi?


*


----------



## Rollmops (20 Juin 2007)

OK ! Tout fonctionne, excuse-moi,  j'avais fait une erreur de transcription.

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 ?


----------



## canibal (21 Juin 2007)

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


----------



## Rollmops (21 Juin 2007)

Merci 

J'ai essay&#233; la commande "*more*" que je ne connaissais pas mais je n'arrive pas &#224; la faire fonctionner. Peux-tu me dire o&#249; &#231;a coince ? 

J'ai essay&#233; :

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

&#231;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
 
&#231;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$


----------



## FjRond (21 Juin 2007)

Rollmops a dit:


> 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 ?
> 
> ...


Il y a deux erreurs:
more (comme less) ne peut lire que des fichiers texte .txt, ou encore les scripts .sh, etc. (c'est-à-dire du texte pur);
il aurait fallu mettre une espace entre le chemin du répertoire courant et la commande more.



Rollmops a dit:


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


Là, c'est l'espace entre "Docus/" et "LETTRE\"


----------



## canibal (21 Juin 2007)

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


----------



## bompi (21 Juin 2007)

Je ne saurais trop conseiller de saines lectures, comme celle-ci, celle-ci ou encore celle-l&#224;. Si la l'anglo-am&#233;ricain te rebute, tu as aussi cette traduction.


----------



## Rollmops (21 Juin 2007)

Merci à tous pour vos bons conseils.  Je vais essayer de les mettre en application.


----------

