Pergunta

Então, digamos que eu estou usando o Python ftplib para recuperar uma lista de arquivos de log de um servidor FTP. Como eu iria analisar essa lista de arquivos para obter apenas os nomes de arquivo (a última coluna) dentro de uma lista? Veja o link acima, por exemplo saída.

Foi útil?

Solução

Usando retrlines () provavelmente não é a melhor idéia lá, uma vez que apenas imprime para o console e para que você teria que fazer coisas complicadas para chegar até a essa saída. A melhor aposta provavelmente seria usar o método nlst (), que retorna exatamente o que você quer:. Uma lista dos nomes de arquivo

Outras dicas

Este melhor resposta

Você pode querer usar ftp.nlst() vez de ftp.retrlines(). Ele lhe dará exatamente o que você quer.

Se você não pode, leia o seguinte:

Geradores para sysadmin processa

Em seu agora famoso revisão, Gerador truques para Sistemas programadores Uma Introdução , David M. Beazley dá um monte de receipes a resposta a este tipo de problema de dados com wuick e código reutilizável.

por exemplo:

# empty list that will receive all the log entry
log = [] 
# we pass a callback function bypass the print_line that would be called by retrlines
# we do that only because we cannot use something better than retrlines
ftp.retrlines('LIST', callback=log.append)
# we use rsplit because it more efficient in our case if we have a big file
files = (line.rsplit(None, 1)[1] for line in log)
# get you file list
files_list = list(files)

Por que não gerar imediatamente a lista?

Bem, é porque fazê-lo desta oferta maneira que você muita flexibilidade: você pode aplicar qualquer gerador intermediária para arquivos de filtro antes de transformá-lo em files_list: é como tubo, adicione uma linha, você adicionar um processo sem superaquecimento (já que é geradores ). E se você se livrar off retrlines, ainda trabalho seja ainda melhor, porque você não armazenar a lista até mesmo uma vez.

EDIT: Bem, eu li o comentário para a outra resposta e diz que este trabalho não se houver qualquer espaço no nome

.

Cool, isso vai ilustrar porque este método é útil. Se você quer mudar alguma coisa no processo, você apenas muda uma linha. Swap:

files = (line.rsplit(None, 1)[1] for line in log)

e

# join split the line, get all the item from the field 8 then join them
files = (' '.join(line.split()[8:]) for line in log)

Ok, isso pode não ser óbvio aqui, mas para grandes scripts de processamento em lote, é bom: -)

E um método um pouco menos ideal, a propósito, se você estiver preso usando retrlines (), por algum motivo, é passar uma função como o segundo argumento para retrlines (); ele vai ser chamado para cada item na lista. Então, algo como isto (supondo que você tem um objeto FTP chamado 'ftp') iria funcionar tão bem:

filenames = []
ftp.retrlines('LIST', lambda line: filenames.append(line.split()[-1]))

A lista 'nomes' será, então, uma lista dos nomes de arquivo.

Existe alguma razão para que ftplib.FTP.nlst () não vai funcionar para você? Acabei de verificar e ele retorna apenas os nomes dos arquivos em um determinado diretório.

Uma vez que cada nome de arquivo nos começos de saída na mesma coluna, tudo que você tem a fazer é obter a posição do ponto na primeira linha:

drwxrwsr-x 5 ftp-usr pdmaint 1536 Mar 20 09:48 .

Em seguida, a fatia de nome de ficheiro para fora das outras linhas usando a posição do referido ponto como o índice de partida.

Uma vez que o ponto é o último caractere na linha, você pode usar o comprimento da linha menos 1 como o índice. Assim, o código final é algo como isto:

lines = ftp.retrlines('LIST')
lines = lines.split("\n") # This should split the string into an array of lines

filename_index = len(lines[0]) - 1
files = []

for line in lines:
    files.append(line[filename_index:])

Se o servidor FTP suporta o comando MLSD, em seguida, consulte a secção “caso único diretório” de essa resposta .

Use uma instância (digamos ftpd) da classe FTPDirectory, chame seu método .getdata com instância ftplib.FTP conectado na pasta correta, então você pode:

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]

Eu acredito que ele deve trabalhar para você.

file_name_list = [' '.join(each_file.split()).split()[-1] for each_file_detail in file_list_from_log]

NOTAS -

  1. Aqui eu estou fazendo uma suposição de que você deseja que os dados do programa (lista), e não no console.

  2. each_file_detail é cada linha que está sendo produzido pelo programa.

  3. '' .join (each_file.split ())

Para substituir vários espaços por 1 espaço.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top