Como listar um nome de arquivo por linha de saída no Linux?

229

Estou usando o ls -acomando para obter os nomes de arquivo em um diretório, mas a saída está em uma única linha.

Como isso:

.  ..  .bash_history  .ssh  updater_error_log.txt

Eu preciso de uma alternativa embutida para obter nomes de arquivos, cada um em uma nova linha, assim:

.  
..  
.bash_history  
.ssh  
updater_error_log.txt
fixxxer
fonte
3
ls tem como objetivo exibir uma lista para consumo humano. Se você estiver usando ls para qualquer outro propósito (como, por exemplo, obter uma lista de arquivos em um script para iterar), certamente estará usando a ferramenta errada.
Juliano
2
@ juliano - É para ser consumido por um script python, na verdade. Por que você chama isso de uma ferramenta errada?
Fixxxer
1
@fixxer No momento em que você lspassar para o python, lsproduzirá um arquivo por linha, como expliquei na minha resposta.
Peter G.
6
@fixxxer: Então você está realmente usando errado. Ele formata a listagem para saída no terminal do usuário. Ele pode substituir caracteres especiais no nome do arquivo, pode omitir caracteres com significado especial, etc ... Em outras palavras, ls formata uma lista para o usuário. Você quer nomes de arquivos não formatados. Alguma razão especial para você não estar usando o módulo 'glob' do python? docs.python.org/library/glob.html Existem também 'fnmatch', 'dircache' e outros.
Juliano
@fixxer Você realmente fez lsa saída para pythone observou a saída de linha única em python?
Peter G. #

Respostas:

430

Use a -1opção (observe que esse é um dígito "um", não uma letra minúscula "L"), assim:

ls -1a

Primeiro, porém, verifique se seus lsapoios -1. Coreutils GNU (instalados em sistemas Linux padrão) e Solaris fazem; mas em caso de dúvida, use man lsou ls --helpou verifique a documentação. Por exemplo:

$ man ls
...
       -1     list one file per line.  Avoid '\n' with -q or -b
Bert F
fonte
2
1 Eu não sabia sobre -1 (sim -l (ell não um)) Mostra no homem-página, mas eu estive lendo-o como um ell o tempo todo :)
slashmais
@slashmais - Ah, bom ponto - fácil de enganar. Eu esclareci na resposta.
Bert F
1
@dty: para GNU, você começa esta documentado na ls --helpsaída ... sempre instalados ;-)
Tony Delroy
3
Pesquisado no Google linux ls one file per linee este foi o artigo principal. Não consigo acreditar o quão prolífica é a resposta escolhida ou que essa resposta tem menos votos do que a resposta que você deseja. ls -1ftw.
crantok
3
lsassume o -1comportamento padrão quando a saída não está conectada ao terminal.
precisa saber é o seguinte
132

Sim, você pode criar facilmente lsum nome de arquivo por linha:

ls -a | cat

Explicação: O comando lsdetecta se a saída é para um terminal ou arquivo ou tubo e se ajusta de acordo.

Portanto, se você usar o ls -apython, ele funcionará sem nenhuma medida especial.

Peter G.
fonte
2
Uau, isso é brilhante. A vantagem sobre a resposta aceita - este realmente funciona em Android / adb shell - onde lsé apenas algumas despojada versão de modo não suporta-1
mkilmanas
Como você evitaria os arquivos " .e .." exibidos na saída?
matanster 26/09/19
@matanster: Depende, você quer ver arquivos de ponto? Caso contrário, basta soltar a opção -a.
Peter G.
29

Ls foi projetado para consumo humano e você não deve analisar sua saída .

Nos scripts shell, existem alguns casos em que a análise da saída de ls funciona é a maneira mais simples de obter o efeito desejado. Como ls pode manipular caracteres não ASCII e controlar nomes de arquivos, esses casos são um subconjunto daqueles que não exigem a obtenção de um nome de arquivo ls.

Em python, não há absolutamente nenhuma razão para invocar ls. Python possui todas lsas funcionalidades incorporadas. Use os.listdirpara listar o conteúdo de um diretório e / os.statou osobter metadados do arquivo. Outras funções nos osmódulos provavelmente também serão relevantes para o seu problema.


Se você estiver acessando arquivos remotos pelo ssh, uma maneira razoavelmente robusta de listar nomes de arquivos é através do sftp:

echo ls -1 | sftp remote-site:dir

Isso imprime um nome de arquivo por linha e, diferentemente do lsutilitário, sftpnão altera caracteres não imprimíveis. Você ainda não poderá listar de maneira confiável os diretórios nos quais um nome de arquivo contém uma nova linha, mas isso raramente é feito (lembre-se disso como um problema de segurança em potencial, não um problema de usabilidade).

Em python (lembre-se de que os metacaracteres do shell devem ser escapados remote_dir):

command_line = "echo ls -1 | sftp " + remote_site + ":" + remote_dir
remote_files = os.popen(command_line).read().split("\n")

Para interações mais complexas, consulte o modo de lote do sftp na documentação.

Em alguns sistemas (Linux, Mac OS X, talvez alguns outros, mas definitivamente não o Windows), uma abordagem diferente é montar um sistema de arquivos remoto através do ssh com sshfs e depois trabalhar localmente.

Gilles 'SO- parar de ser mau'
fonte
Estou conectado via SSH à máquina remota. Não encontrei nenhuma maneira de executar uma função python como os.listdir na máquina remota em uma única linha. Portanto, esta questão. Não quero escrever um script para simplesmente listar arquivos. Existe alguma outra maneira de contornar esse problema?
Fixxxer
@fixxxer: ssh muda a situação, é o tipo de coisa que você deveria ter mencionado na sua pergunta original! Eu acho que o sftp é apropriado para o seu caso de uso.
Gilles 'SO- stop be evil'
Sinto muito pela confusão. Existe uma maneira de inserir a senha no "linha de comando" também?
Fixxxer
@fixxxer: Eu não sei, os autores do ssh desaprovam senhas armazenadas em texto sem formatação e tendem a não facilitar isso. Você realmente deve configurar a autenticação baseada em chave (há muitos tutoriais na Web e perguntas no superuser.com sobre isso).
Gilles 'SO- stop be evil'
11

você pode usar ls -1

ls -l também fará o trabalho

ILF
fonte
A resposta principal já menciona exatamente as coisas que você disse. também a pergunta diz especificamente ls -lque não deve ser usada.
DevX 30/11/19
2

Fácil, desde que seus nomes de arquivos não incluam novas linhas:

find . -maxdepth 1

Se você estiver enviando isso para outro comando, provavelmente preferirá separar seus nomes de arquivos por bytes nulos, em vez de novas linhas, pois bytes nulos não podem ocorrer em um nome de arquivo (mas as novas linhas podem):

find . -maxdepth 1 -print0

Imprimir isso em um terminal provavelmente será exibido como uma linha, porque bytes nulos normalmente não são impressos. Alguns programas podem precisar de uma opção específica para lidar com entradas delimitadas por nulos, como sort's -z. Da mesma forma, seu próprio script precisaria explicar isso.

8bittree
fonte