Artigo original: Python List Files in a Directory Guide - listdir VS system("ls") Explained with Examples

🔹 Boas-vindas

Se você quer aprender como essas funções atuam internamente e como você pode usar todo o poder delas, este artigo é para você.

Começaremos pelos conceitos que são essenciais para se trabalhar com as funções listdir e system:

  • O módulo os, integrado no Python, e como importá-lo.
  • Os conceitos de "diretório" e "diretório atual".
  • Como obter e mudar o seu diretório atual.
  • A diferença entre um caminho absoluto e um caminho relativo.

Depois, aprofundaremos nas funções propriamente ditas:

  • Como trabalhar com a função listdir e quando usá-la.
  • Como trabalhar com a função system("ls") e quando usá-la.
  • Exemplos de ambas e de como elas funcionam internamente.

Vamos começar! ⭐

🔸 O módulo OS

As duas funções que discutiremos, listdir() e system(), fazem parte do módulo os. Esse módulo inclui funções que são usadas para interagir com o sistema operacional, realizando ações como:

  • Criar um diretório
  • Renomear um diretório existente.
  • Remover um diretório.
  • Mostrar o caminho para o seu diretório atual.
  • E muito mais!

💡 Dicas:

  • Um diretório é o que comumente chamamos de "pasta", onde guardamos arquivos e/ou outros diretórios, criando uma hierarquia de "diretórios dentro de diretórios" (também chamados de subdiretórios). Um exemplo de diretório é a pasta "Documentos".
  • Um módulo é um arquivo que contém códigos em Python relacionados.

Como importar o módulo OS

Para usar o módulo os no seu script, você precisa "importá-lo". Importar um módulo significa ganhar acesso a todas as funções e variáveis que estão armazenadas no módulo. Importamos um módulo quando queremos usar o seu código no nosso script.

Para importar o módulo os, você simplesmente precisa incluir esta linha no início do seu script Python ou executá-la no seu shell interativo:

import os

Isso dará acesso a todas as funções definidas no módulo os.

💡 Dica: o módulo os foi instalado quando você instalou o Python 3. Então, você poderá utilizá-lo imediatamente.

Para poder utilizar as funções do módulo os, você precisará adicionar o prefixo os. antes do nome da função que deseja chamar, desta maneira:

os.<função>(<parâmetros>)

Por exemplo:

os.mkdir("Nova Pasta")

Como importar funções individualmente

Se você trabalhará apenas com uma ou duas funções do módulo, pode importá-las individualmente usando a seguinte sintaxe:

from <módulo> import <função1>, <função2>, ...

Por exemplo:

from os import listdir, system

Nesse caso, você pode chamar essas funções no seu script normalmente, sem adicionar o prefixo os., desta maneira:

<função>(<parâmetros>)

Por exemplo:

mkdir("Nova Pasta")

🔹 Diretório atual

Agora, vamos ver um conceito muito importante que você precisa saber antes de começar a trabalhar com listdir e system. Seu diretório atual, como o nome diz, é o diretório (pasta) em que você está trabalhando no momento.

Você pode verificar o seu diretório atual com essa função do módulo os:

os.getcwd()

Isso mostrará o caminho do seu diretório atual.

💡 Dica: cwd significa "current working directory", que, traduzindo para o português, significa "diretório atual".

A partir do shell interativo

Se eu executo o comando em um shell interativo (Windows), eu vejo isto:

>>> os.getcwd()
'C:\\Users\\estef\\AppData\\Local\\Programs\\Python\\Python38-32'

Esse é o caminho completo para o meu diretório atual:

'C:\\Users\\estef\\AppData\\Local\\Programs\\Python\\Python38-32'

A partir de um script

Se eu executo o comando a partir de um script, como este:

import os
print(os.getcwd())

Eu vejo:

C:\Users\estef\Documents\freeCodeCamp\freeCodeCamp News\listdir vs system

O caminho completo para o script (a sua localização no sistema, na hierarquia de diretórios).

💡 Dica: se eu executo um script (um arquivo em Python), o diretório atual nem sempre é o diretório onde o script está localizado, mas é o diretório de onde o script foi executado.

Como mudar o seu diretório atual

Você pode mudar o seu diretório atual com este comando do módulo os:

os.chdir(<caminho>)

Você precisará especificar o caminho para o novo diretório atual, passando como argumento uma string. Essa string pode ser tanto um caminho absoluto como um caminho relativo.

💡 Dica: um caminho absoluto especifica toda a sequência de diretórios que você precisa passar para chegar em um diretório qualquer. Esse caminho começa no diretório raiz do seu sistema.

Por exemplo:

>>> import os
>>> os.chdir(r"C:\Users\estef\Documents\FreeCodeCamp\freeCodeCamp News\9 - listdir vs system")

# Verificando o diretório atual:
>>> os.getcwd()
'C:\\Users\\estef\\Documents\\FreeCodeCamp\\freeCodeCamp News\\9 - listdir vs system'

Observe que adicionei um r antes do caminho absoluto para converter a string em uma raw string. Se você adicionar uma \ na string e não adicionar o r, você receberá um erro, porque o símbolo \ será tratado como um caractere especial.

Como alternativa, você pode substituir as contrabarras \ por barras / no caminho:

>>> os.chdir("C:/Users/estef/Documents/FreeCodeCamp/freeCodeCamp News/9 - listdir vs system")

# Verificando o diretório atual:
>>> os.getcwd()
'C:\\Users\\estef\\Documents\\FreeCodeCamp\\freeCodeCamp News\\9 - listdir vs system'
  • Um caminho relativo especifica o caminho que você deseja seguir para encontrar o diretório de destino, mas agora o caminho começa do seu diretório atual. Ele é mais curto e simples que o caminho absoluto.

Por exemplo, se o seu diretório atual contém um subdiretório (pasta) Directory 1, você pode mudar para esse diretório usando um caminho relativo (imagine como uma pasta dentro de outra pasta, e estamos indo cada vez mais fundo na hierarquia), deste modo:

>>> import os
>>> os.chdir(".\Directory 1")

# Verificando o diretório atual
>>> os.getcwd()
'C:\\Users\\estef\\Documents\\FreeCodeCamp\\freeCodeCamp News\\9 - listdir vs system\\Directory 1'

💡 Dica: o ponto (.) no começo do caminho relativo .\Directory 1 representa o diretório atual. Dois pontos ( ..) é usado para subir na hierarquia, para o diretório "pai".

Agora que você tem todo esse conhecimento, vamos entender de fato como listdir e system funcionam. Então, vamos ver essas funções em mais detalhes.

🔸 Listdir

Começaremos com a função listdir. Vamos revelar seus mistérios.

Propósito e retorno

De acordo com a documentação do Python, o propósito dessa função é:

Retornar uma lista contendo os nomes das entradas no diretório fornecido pelo caminho.

Basicamente, essa função retorna uma lista com os nomes de todos os arquivos e diretório que podem ser encontrados dentro de um diretório que você especifica quando chama a função.

💡 Dica: a lista não terá uma ordem específica, mesmo que você ordene normalmente os elementos alfabeticamente.

Sintaxe e parâmetro

Para chamar listdir, precisamos usar esta sintaxe:

image-9
Aqui, "path" significa "caminho"

O parâmetro caminho é precisamente o caminho absoluto ou relativo para o diretório que você quer visualizar. No Python 3.2 ou superior, esse parâmetro é opcional. Por padrão, o caminho mostrará o seu diretório atual se você não passar um argumento.

image-12
Aqui, "Current Working Directory" significa "diretório atual"

Lembre-se de que você precisa importar o módulo os antes de chamar essa função.

💡 Dica: se você usa essa declaração de importação from os import listdir para importar a função individualmente, poderá omitir o prefixo os., deste modo:

image-10
Aqui, "path" significa "caminho"

Casos de uso e vantagens

A função listdir é muito útil, pois ela funciona em qualquer sistema operacional no qual o Python rode. Então, se o Python estiver instalado no seu dispositivo, essa função funcionará corretamente.

Agora, vamos falar um pouco sobre o retorno dessa função. Já que ela retorna uma lista, podemos armazenar essa lista em uma variável e trabalhar com ela no nosso programa.

Por exemplo, podemos querer fazer algo com todos os arquivos de um diretório, como converter as imagens para preto e branco ou alterar o seu conteúdo. Poderíamos fazer isso com um laço for, deste modo:

images = os.listdir(<caminho>)

for image in images:
	# Fazer algo com a imagem

Certamente, você precisaria definir o que acontecerá dentro do laço, mas esse é apenas um exemplo do que você poderia fazer com essa função.

Incrível, não é?

No entanto, ter arquivos e diretórios na mesma lista pode ser um pouco problemático se você quer trabalhar com um laço for, certo? Precisaríamos adicionar uma validação para verificar o tipo de cada elemento. Como podemos fazer uma lista que contém apenas nomes de arquivos (sem diretórios) ou vice -versa?

Vamos ver! ✨

Incluir apenas arquivos

Se você quer "filtrar" a lista retornada por os.listdir() para incluir apenas arquivos (sem diretórios), você pode usar essa linha de código:

list(filter(os.path.isfile, os.listdir(<caminho>)))

💡 Dica: você pode personalizar o argumento <caminho> ou omiti-lo para usar o seu diretório atual.

Vamos ver um exemplo usando o meu diretório atual (estou usando o Windows):

image-23

Meu diretório (pasta) tem:

  • Dois subdiretórios (pastas dentro da pasta principal)
  • Um arquivo PowerPoint
  • Uma imagem (arquivo .png)
  • Um script em Python

Se eu chamar a função listdir do arquivo script.py e exibir a lista que foi retornada:

print(os.listdir())

Esta é a saída:

['Diagrams.ppt', 'Directory 1', 'Directory 2', 'listdir vs system.png', 'script.py']

Você pode ver que todos os arquivos e diretórios do meu diretório atual foram incluídos.

Para filtrar a lista para conter apenas arquivos, nós podemos usar esta declaração:

print(list(filter(os.path.isfile, os.listdir())))

Agora, a saída é esta:

['Diagrams.ppt', 'listdir vs system.png', 'script.py']

Observe como os diretórios foram "filtrados", exatamente como queríamos.

Incluir apenas diretórios

Do mesmo modo, se você quer "filtrar" a lista para incluir apenas diretórios, você pode usar esta linha de código:

list(filter(os.path.isdir, os.listdir(<caminho>)))

Agora, a saída é:

['Directory 1', 'Directory 2']

Exatamente como queríamos. Porém, como essa declaração funciona internamente? Vamos ver.

Como filter() funciona internamente

A função filter é chamada usando a seguinte sintaxe:

filter(<função>, <lista>)

Ela basicamente "filtra" os elementos do segundo argumento (a lista) baseado no valor booleano retornado quando chamada a função passada como primeiro argumento (os.path.isfile() ou os.path.isdir() nos seus respectivos comandos):

print(list(filter(os.path.isfile, os.listdir())))
list(filter(os.path.isdir, os.listdir()))

Estas duas funções:

os.path.isfile(<caminho>)

os.path.isdir(<caminho>)

retornam True se o argumento é um arquivo ou um diretório, respectivamente.

Baseado nesses valores booleanos, os elementos da lista serão incluídos (ou não) na lista "filtrada". Os elementos da lista retornada pela função os.listdir() são passados um por um para essas funções para verificar se eles são arquivos (ou diretórios, respectivamente).

Por exemplo, se você tem esta linha de código:

filter(os.path.isfile, os.listdir())))

e se os.listdir() retorna esta lista:

['Diagrams.ppt', 'Directory 1', 'Directory 2', 'script.py']

O primeiro elemento da lista ('Diagrams.ppt') é passado como argumento para os.path.isfile() para verificar se ele é um arquivo:

os.path.isfile('Diagrams.ppt') # True
image-30

A chamada dessa função retorna True. Então, é um arquivo e é incluído na lista.

No entanto, se o elemento é um diretório:

os.path.isfile('Directory 1') # False
image-31

A chamada da função retorna False. Então, o elemento não é incluído na lista. Esse processo continua para cada elemento na lista até que a nova lista contenha apenas nomes de arquivos.

Assim, já que filter() retorna um iterable, criamos uma lista a partir desse iterable usando list():

list(filter(os.path.isfile, os.listdir()))

Logo, imprimimos essa lista, já que estamos trabalhando com um arquivo em Python (script):

print(list(filter(os.path.isfile, os.listdir())))

💡 Dica: você pode identificar visualmente se um elemento da lista representa um arquivo ou um diretório vendo se ele tem uma extensão (tipo) após seu nome. Por exemplo: Diagrams.ppt tem a extensão .ppt, o que mostra que ele é um arquivo do PowerPoint, mas um diretório não possui um extensão, como 'Directory 1'.

image-32--1-

🔹 System("ls")

Agora que você sabe como trabalhar com o listdir, vamos ver como a função system() funciona internamente e como você pode usá-la.

Finalidade

De acordo com a documentação do Python, o propósito da função system() é:

Executar o comando (uma string) em um subshell

Basicamente, essa função pega um comando (como uma string) e o executa.

Neste caso, o comando que estamos passando é o 'ls' , um comando Unix usado no Linux para exibir o conteúdo de um diretório no stdout.

Diferente de listdir, a função system() não retornará uma lista se você passar o comando 'ls', ela apenas exibirá a lista de arquivos e diretórios no stdout. Por isso, você deve usá-la apenas se deseja visualizar a lista sem trabalhar com ela no seu programa.

Sintaxe e parâmetros

Para chamar essa função, você precisará usar essa sintaxe:

image-15
Aqui, "command" significa "comando"

O único argumento é o comando que você deseja executar, como uma string (envolta por aspas ou apóstrofos).

Particularmente, o comando ls permite que você veja o conteúdo do seu diretório atual.

Por exemplo, se esse é o meu diretório atual (três arquivos em Python e um subdiretório):

image-17

Chamamos a função system(), deste modo:

>>> import os
>>> os.system("ls")

Este é o resultado:

'Directory 1'  'file 1.py'  'file 2.py'   main.py
0

Podemos ver o stdout no console (a lista de arquivos e diretórios):

'Directory 1'  'file 1.py'  'file 2.py'   main.py

e o valor retornado:

0

💡 Observação: para esses exemplos da função system(), estamos trabalhando com uma ferramenta de linha de comando on-line, chamada Repl.it, já que meu computador tem o Windows instalado e o comando ls não é reconhecido pelo prompt de comando padrão.

Limitações

Uma das principais limitações dessa função é o fato de que o comando passado como argumento deve ser reconhecido pelo sistema operacional ou pelo ambiente em que você está trabalhando.

Por exemplo, o comando ls não será reconhecido no Windows no prompt de comando padrão. Você verá esse erro caso tente executá-lo:

'ls' não é reconhecido como um comando interno ou externo, um programa operável ou um arquivo em lotes.

Um comando similar no Windows seria o comando 'dir':

os.system('dir')

💡 Dica: existem alternativas para rodar o comando ls no Windows, como usar um terminal que reconhece comandos do Unix, mas, por padrão, o Windows não reconhece o comando 'ls'.

Valor de retorno

De acordo com a documentação do Python:

No Unix, o valor de retorno é o status de saída do processo codificado no formato especificado para wait().

e...

No Windows, o valor de retorno é aquele retornado pelo shell do sistema após a execução do comando.

💡 Dica: observe que essa função não retorna uma lista. Ela apenas mostra a lista no stdout. Então, você não pode armazená-la em uma variável, como fizemos com o listdir.

Variações do comando ls

Uma das principais funções do os.system('ls') é ter várias opções úteis e interessantes para personalizar a apresentação da saída. Vejamos algumas delas.

Opção 1: podemos mostrar mais informações sobre os arquivos e diretórios, como seus tamanhos, localização, data e hora da última alteração usando o comando ls -l.

>>> import os
>>> os.system('ls -l')
total 12
drwxr-xr-x 1 runner runner  0 Apr  3 18:23 'Directory 1'
-rw-r--r-- 1 runner runner 11 Apr  3 18:38 'file 1.py'
-rw-r--r-- 1 runner runner 11 Apr  3 18:38 'file 2.py'
-rw-r--r-- 1 runner runner 11 Apr  3 18:38  main.py
0

Opção 2: para reconhecer visualmente diretórios mais rapidamente, podemos usar ls -F, que adiciona uma barra / no final dos seus nomes (veja Directory 1/ abaixo).

>>> import os
>>> os.system('ls -F')
'Directory 1'/  'file 1.py'  'file 2.py'   main.py
0

Opção 3: para ordenar os arquivos pelo tamanho, podemos usar o comando ls -lS.

>>> import os
>>> os.system('ls -lS')
total 12
-rw-r--r-- 1 runner runner 11 Apr  3 18:38 'file 1.py'
-rw-r--r-- 1 runner runner 11 Apr  3 18:38 'file 2.py'
-rw-r--r-- 1 runner runner 11 Apr  3 18:38  main.py
drwxr-xr-x 1 runner runner  0 Apr  3 18:23 'Directory 1'
0

Existem muitas outras opções para personalização que podem ajudar atingir um objetivo específico. Aqui, você pode encontrar mais informações sobre o comando ls e sobre como utilizar todo o seu poder.

🔸 Resumo de listdir x system("ls")

  • Propósito: listdir retorna a lista de nomes de arquivos e diretórios no caminho especificado (por padrão, o diretório atual) enquanto system("ls") apenas os mostra no stdout.
  • Sistema operacional: listdir pode ser utilizado independentemente do sistema operacional em que você está trabalhando. Em contrapartida, system('ls') tem que ser executado em um sistema operacional ou ambiente que reconheça o comando 'ls'.
  • Personalização: você pode filtrar a lista retornada pelo listdir se precisar remover arquivos e diretórios usando a função filter(). Também é possível passar opções adicionais para personalizar a saída de system('ls').

Eu realmente espero que você tenha gostado deste artigo e o tenha achado útil. Agora, você pode trabalhar com essas funções nos seus projetos em Python. Confira os cursos on-line da autora e siga-a no Twitter. ⭐️