1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

C - listar ficheiros de um directório - UNIX API

Discussão em 'Programação' iniciada por OubeLa, 13 de Outubro de 2008. (Respostas: 9; Visualizações: 1641)

  1. OubeLa

    OubeLa Power Member

    Imaginem que estou num directório qualquer e quero saber quais os ficheiros presentes nesse directório. A ideia é percorrer todos os directórios, portanto, tenho de saber os ficheiros de cada directório e saber qual desses ficheiros é um sub directório (que não é nada mais do que um ficheiro especial). Que tipo de funções da API de UNIX devo usar?

    Cumprimentos
     
    Última edição: 18 de Outubro de 2008
  2. VuDu

    VuDu Power Member

  3. r3pek

    r3pek Power Member

    VuDu: desculpa la, mas não me parece que o ls seja a man page mais indicada como API para o que ele quer. Até porque o ls não é uma API, é um comando! E deve-se evitar ao maximo o uso do exec!!

    Como tal, sir_atmc, começa por esta man page e vai descascando a partir daí. se fores lendo as sugestões de man pages tens a informação toda que necessitas. De qualquer maneira se precisares de ajuda avisa.
    http://linux.about.com/library/cmd/blcmdl3_opendir.htm
     
  4. sapropel

    sapropel Power Member

    o r3pek já respondeu, mas sem querer desvalorizar a resposta dele, tem de ser C? se sim tudo bem, se não então fica mais uma sugestão boost::filesystem
     
  5. OubeLa

    OubeLa Power Member

    Obrigado a todos. Sim, convém ser em C usando a API do UNIX.
     
  6. bsd

    bsd Power Member

    Tens também um interface de mais alto nível que o opendir/readdir, que é o glob. Dá jeito principalmente quando queres wildcards.
    Também acho preferível ler a documentação em http://www.unix.org/single_unix_specification/.
     
  7. OubeLa

    OubeLa Power Member

    Estou aqui com um problema.

    Tenho o meu programa num certo directório. Esse directório é representado por ".".

    Código:
    char *path = ".";
    Depois abro esse directório usando o opendir (e usando a strcut dirent) e o readdir. Para verificar se um ficheiro é uma pasta uso a struct stat disponível em <sys/stat.h>

    Código:
    dp = opendir (path);
            if (dp != NULL)
            {
                while (ep = readdir (dp)) {
                    // Não percorrer os directórios '.' e '..'
                    if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
                        // If Directory, call function again
                        stat(ep->d_name, &st);
                        if (S_ISDIR(st.st_mode)) {
                            printf("Directorio - %s\n", ep->d_name);
    
    (....)
    Ora, se estiver a usar o directório inicial como sendo "." funciona bem, ele detecta as pastas, mas se por exemplo quiser que o directorio inicial seja "/" ou "/home" ele já não detecta os ficheiros como sendo pastas. Alguma ideia?
     
  8. bsd

    bsd Power Member

    Ó sir_atmt, já é muito tarde, os teus olhos já estão cansados.

    O problema é simplesmente que não estás a passar ao stat() o pathname completo.

    Repara, eu percorro o directório /home/abc e tenho lá os ficheiros ".", "..", "bcd" e "cde". Eu tenho que fazer stat é de "/home/abc/bcd" e de "/home/abc/cde", tu estás a fazer stat de "bcd" e de "cde", como queres que ele adivinhe os directórios onde eles estão?

    Vais ter de concatenar estes nomes com o do directório inicial. E vai surgir-te um caso especial/ excepção. No caso geral tens de concatenar "/home/abc" com "/" e com "cde", excepto quando o directório inicial é "/home/abc/" ou "/"; neste caso seria só "/" com "cde". Agora, a informação que aproveito para te dar é que não faz mal teres duas barras de seguida, "/home/abc//cde" é a mesma coisa que "/home/abc/cde", ou seja, não precisas de ter um caso especial.

    Tenho ainda que te dizer que o readdir é um bocado obsoleto. Hoje em dia temos de partir do princípio que o programa vai ser multithreaded mais cedo ou mais tarde. Ora, o readdir() devolve-te um ponteiro para um buffer estático interno e por isso é não-reentrant; não pode ser usado num programa multithreaded ou numa função recursiva (ou nalgumas).

    Habitua-te desde já a usar o equivalente reentrant readdir_r(). E quem diz essa, diz também localtime_r, etc, etc...

    Bom sono.

    PS: a constante que tem a dimensão máxima de um pathname é PATH_MAX e está definida em unistd.h
     
  9. OubeLa

    OubeLa Power Member

    A questão das threads será abordada no próximo trabalho, estou a trabalhar exclusivamente com processos. Mas muito obrigado pelas dicas, de facto foi muito estupido esse erro. Há que dar o desconto porque estou doente (gripe) ;)
     
  10. bsd

    bsd Power Member

    Não faz mal, eu também estou com gripe.

    Mesmo com processos. A propriedade de reentrancy não é só importante em multithreading. Por exemplo, tu estás a fazer uma função recursiva, certo?

    Imagina que a função, depois de se chamar a si própria, volta a precisar do que está em ep->d_name? O seu conteúdo já não terá nada a ver!

    Acho que se deve optar por ser safe by default. No fundo, o que estás a dizer é "eu controlo", "eu sei que não volto a usar ep->d_name depois da função se chamar a si própria", "eu consigo". Daqui a 6 meses pretendes reutilizar o código, e depois tens um erro que demoras vários dias a apanhar.
     

Partilhar esta Página