Liste uniquement les sous répertoires d'un répertoire en c

Bonjour,
Le code lsd.c suivant :[code]
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

int
main(int argc, char *argv[]) {
int i;
struct dirent *dp;
struct stat s;
DIR *dir;

if((argc > 1) && !strncmp(argv[1], "-v", 3)) {
	fputs("lsd-"VERSION"\n", stdout);
	exit(EXIT_SUCCESS);
}
for(i = 0; i < argc; i++)
	if((dir = opendir(argv[i]))) {
		fchdir(dirfd(dir));
		do
			if((dp = readdir(dir))
				&& (stat(dp->d_name, &s) != -1)
				&& S_ISDIR (s.st_mode)
				&& !access(dp->d_name, X_OK))
				puts(dp->d_name);
		while(dp);
		closedir(dir);
	}
return 0;

}[/code]produit un programme qui, lancé avec le nom d’un répertoire en argument va lister tous ses sous-répertoires comme
la commandels -dU .*/ */Du moins ce que je crois, or dans le listage les répertoires . et … sont listés deux fois, est-ce que quelqu’un saurait me dire pourquoi?

Bonjour Eol,

Je n’ai pas bien compris ton problème peux tu lister la commande et ton résultat?.

pour moi:

$ lsd . .. . tmp

Bon en fait, je l’avais pas essayé dans un terminal mais dans un script où la sortie de lsd était renvoyée ailleurs,
je viens de l’essayer dans un terminal et ça marche nickel, juste à le piper dans sort pour l’avoir dans l’ordre.
Pourtant le même script avec ls -dU */ .*/ marchait sans souci …
le script qui s’appelle lsdsh est :#!/bin/sh prompt=Listedir dir=`lsd $PWD | sort | dmenu -p "$prompt: $PWD" -i` [ -z $dir ] if [ $? = 1 ]; then cd $dir && lsdsh ; else actions fi
Dans dmenu j’obtiens. . .. .. puis la liste de mes répertoires
Si je remplace la ligne dir=`lsd $PWD | sort | dmenu -p "$prompt: $PWD" -i`
pardir=`ls -dU */ .*/ | dmenu -p "$prompt: $PWD" -i`j’obtiens. .. puis la liste de mes répertoires

edit : Bon apparement, j’ai écrit un peu trop vitelsd ~dans un terminal me donne aussi . et … en double, tous les autres sous répertoires ne sont listés qu’une fois.

2ème edit : le problème n’a lieu que dans mon home.

J’ai pas de duplica chez moi (juste une erreur sur le fputs à la compilation).

Il me semble voir dans ton script que tu fais un dir=`lsd $PWD … puis
un cd dans ce qu’il y a dans dir et tu relance lsd dessus.
Donc si dir = . , cela fais un cd . && lsdsh qui fais un autre lsd de .

il faudrait que tu filtre soit dans ton script soit dans ton C les chemins “.” et “…”
[par exemple dans C par && ((strchr(argv[1],’.’) == NULL) ].

[quote=“Dixippe”]il faudrait que tu filtre soit dans ton script soit dans ton C les chemins “.” et “…”
[par exemple dans C par && ((strchr(argv[1],’.’) == NULL) ].[/quote]
J’ai pas tout suivi tu veut filtrer tout les dossiers caché ?
Sinon vaut mieux utiliser !strcmp(chaine, “.”) et !strcmp(chaine, “…”).

Je ne veux filtrer que les doublons, accessoirement lister les repertoires cachés après les autres mais ça c’est pas prioritaire.

[quote=“Dixippe”]Il faudrait que tu filtre soit dans ton script soit dans ton C les chemins “.” et “…”
[par exemple dans C par && ((strchr(argv[1],’.’) == NULL) ].[/quote]Ça, je ne le souhaite pas car si mon doigt rippe et m’envoie dans un répertoire non désiré,
je suis bien content de revenir en arrière avec en tapant … :wink:

Chez moi ça compile comme ça :x@eol:~/sources/lsd$ make clean install cleaning lsd build options: CFLAGS = -Os -I/usr/lib -DVERSION="0.1" LDFLAGS = -L/usr/lib -lc CC = cc CC lsd.c LD lsd finished installing executable file to /home/x/bin
Mais j’ai ces #[|]}$%³ de doublons qui reviennent de manière aléatoire.

J'ai exécuté ça une cinquantaine de fois sur différents dossiers, jamais de duplicat.

J’ai exécuté ça une cinquantaine de fois sur différents dossiers, jamais de duplicat.

J’ai implanté tes 2 programmes (C et script) et j’ai pas le problème des duplicatas ‘.’ et ‘…’

j’ai juste viré “else actions” du script (j’ai pas compris…).

Tu as “.” et “…” en doublon quand tu donne plusieurs dossier en paramètres non ?
Les dossiers “.” et “…” se trouvant dans tout les dossiers c’est normal. -_-’

Au passage :

do if((dp = readdir(dir)) && (stat(dp->d_name, &s) != -1) && S_ISDIR (s.st_mode) && !access(dp->d_name, X_OK)) puts(dp->d_name); while(dp);
C’est pas très lisible plutôt que ça :

while((dp = readdir(dir)) == 0){ int ret = stat(dp->d_name, &s); if(-1 != ret && S_ISDIR (s.st_mode) && !access(dp->d_name, X_OK)) { puts(dp->d_name); } }
Le while(){} est plus approprié que le do{}while() ici. L’appel à stat() est plus lisible vu comme une instruction que caché dans une condition. Je pense qu’il faut toujours mettre les {} (dans les if, les for ou les while), sauf dans le cas où on le fait en une ligne par exemple :

Non, j’ai des doublons en ne donnant qu’un seul répertoire en argument.

[quote=“MisterFreez”]./ls.c .. | sort | uniq -d
J’ai exécuté ça une cinquantaine de fois sur différents dossiers, jamais de duplicat.[/quote]
Moi non plus en pipant dans sort -u je n’ai pas de doublon :wink: même avec beaucoup de bonne volonté je ne crois pas que ce serait possible.

man sort man uniq
Désolé de faire du RTFM mais tu n’a pas pris en compte l’option “-d” ça fait toute la différence (et ça t’apprendras à poster trop vite :wink: ).

[quote=“MisterFreez”]man sort man uniq
Désolé de faire du RTFM mais tu n’a pas pris en compte l’option “-d” ça fait toute la différence (et ça t’apprendras à poster trop vite :wink: ).[/quote]OK, j’ai été voir pour l’option -d de uniq et je vois ce que tu veux dire.
As tu essayé le programme avec ~ ou / en argument?
Chez moi, piper dans uniq -d me sort aussi les doublons (forcément) mais de manière plus lisible (merci pour l’astuce).

Aucun doublon sauf si je liste deux répertoires (ce qui est logique).

x@eol:~/sources/lsd$ lsd / lib root cdrom bin dev sbin selinux home etc sys tmp proc srv usr . var mnt opt media .. bootx@eol:~/sources$ lsd / . .. lib root cdrom bin dev sbin selinux home etc sys tmp proc srv usr . var mnt opt media .. boot
La même commande lancée de deux répertoires différents donnant deux résultats différents, ça peut sembler normal dans certains cas, mais là non.

File nous ton code actuel.

[quote=“MisterFreez”]File nous ton code actuel.[/quote]Bonjour,
c’est exactement le même qu’au premier post.

Repartons de zéro, ça donne quoi chez toi ça ?

[code]#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

int main(int argc, char** argv){
int i;
char* rep;
DIR* dossier;
struct dirent* fichier;

if(1 == argc){
fprintf(stderr, “Usage : %s [ …]\n”, argv[0]);
return 1;
}

for(i = 1; i < argc; ++i){
rep = argv[i];
dossier = opendir(rep);
if(NULL == dossier){
fprintf(stderr, “Le répertoire %s est inaccessible.\n”, rep);
continue;
}
while(fichier = readdir(dossier)){
if(DT_DIR == fichier->d_type){
printf("%s\n", fichier->d_name);
}
}
}
return EXIT_SUCCESS;
}[/code]