Como gerar apenas nomes de arquivos (com espaços) em ls -Al?


80

Eu devo repetir apenas nomes de arquivos ou diretórios com esta construção:

ls -Al | while read string
do
...
done

ls -Al resultado :

drwxr-xr-x  12 s162103  studs         12 march 28 12:49 personal domain
drwxr-xr-x   2 s162103  studs          3 march 28 22:32 public_html
drwxr-xr-x   7 s162103  studs          8 march 28 13:59 WebApplication1

Por exemplo, se eu tentar:

ls -Al | while read string
do
echo "$string" | awk '{print $9}
done

em seguida, produza apenas arquivos e diretórios sem espaços. Se o arquivo ou diretório tiver espaços como "domínio pessoal", será apenas a palavra "pessoal".

Eu preciso de uma solução muito simples. Talvez exista uma solução melhor do que o awk.


2
Por que não apenas ls -Al *' '*? lsA saída da análise nunca leva a nada de bom.
— manatwork

1
Se você precisar de algo que funcione em qualquer * nix, tente evitar o uso ls -Al | while. Uma maneira simples e mais confiável é for string in *; do echo "$string"; done.
— forcefsck

só precisa dessa construção .. ok, não é simples, qualquer solução!
— Alex Zern #

1
Por que você precisa ls ? A análise lse o "trabalho em todos * nix e não serão interrompidos se algo acontecer" não funcionam bem juntos.
— terdon

Respostas:


99

Você realmente não deve analisar a saída dels . Se for uma tarefa de casa e você precisar, seu professor não sabe do que está falando. Por que você não faz algo assim:

O bom...

find ./  -printf "%f\n"

ou

for n in *; do printf '%s\n' "$n"; done

...o mal...

Se você realmente deseja usar ls, pode torná-lo um pouco mais robusto fazendo algo como isto:

ls -lA | awk -F':[0-9]* ' '/:/{print $2}'

... e o feio

Se você insistir em fazê-lo da maneira errada e perigosa e apenas precisar usar um whileloop, faça o seguinte:

ls -Al | while IFS= read -r string; do echo "$string" | 
    awk -F':[0-9]* ' '/:/{print $2}'; done

Sério, apenas não.


drwx------ 2 s162103 studs 3 oct. 9 2012 .ssh drwxr-xr-x 3 s162103 studs 6 oct. 25 09:02 .subversion drwxrwxrwt 3 s162103 studs 3 nov. 15 2012 .TempoItemsÀs vezes eu tenho data sem tempo, só no ano e embasbacar retornar vazia
— Alex Zern

1
@AlexZern Bem, essa é uma das razões pelas quais você não analisa a saída ls.
— terdon

2
@AlexZern Por que você precisa da -ltroca, afinal? Se tudo o que você deseja são os nomes dos arquivos, basta executar ls -A. Usar -lapenas dificulta sua vida, pois agora você precisa analisar a saída.
— terdon

porque preciso de informações adicionais como acesso, data, proprietário, etc. E eu escrevi um script enorme, que funciona bem, exceto arquivos de impressão e nomes de diretórios com espaços.
— Alex Zern

3
OK então. O que temos aqui é um problema XY . lssimplesmente não é a melhor maneira de conseguir o que você precisa. Por que você não publica uma nova pergunta explicando as informações que deseja coletar e podemos sugerir maneiras de fazê-lo. Como alternativa, você pode usar seu script como está e usar uma das sugestões acima para imprimir apenas o nome. Mas, lsfalando sério, não analise , diga-nos exatamente o que você está tentando fazer em uma nova pergunta.
— terdon

74

Existe alguma razão para ls -A1* não funcionar?

Por exemplo:

$ touch file1 file2 file\ with\ spaces
$ ls -Al
total 0
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file1
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file2
-rw-r--r-- 1 bahamat bahamat 0 Mar 30 22:31 file with spaces
$ ls -A1
file1
file2
file with spaces
$

* Nota: é uma letra maiúscula A e o número um.


4
o -1 é genial. Eu não sabia que estava disponível. (Eu sei, eu sei. RTFM)
— The Lazy Coder

que só funciona para diretório atual, se você deseja listar os nomes de arquivo de outro diretório dizer ~ / projectos então você vai ter caminhos completos em vez de nomes de arquivos
— thecotne

@thecotne no Mac 10.9.5 apenas lista os nomes dos arquivos. Qual sistema operacional você está usando?
— AJP 5/05

Estou executando esta ls ~ / projetos / * A1 sublime-projeto para ls ~ / projetos A1 eu fizer apenas nomes.
— thecotne

3
O @TheLazyCoder não deveria ler o manual.
— C24w

41

Gostaria de saber por que ninguém mencionou este comando simples:

ls -a | sort

2
Brilhante! Alguma idéia de como a tubulação sortfaz com que o bloco com várias colunas seja desmembrado em uma única coluna?
— msciwoj

@msciwoj ele só tem nenhum cadeias separadas por espaços em branco e imprime-las ordenadas separados por linhas finais
— Ben

PERFEITO! Por que este não foi marcado como a resposta real !?
— 夏期劇場

3
Ele funciona aqui porque é lsrevertido para ls -1(saída de coluna única) quando sua saída não vai para um terminal (e desativa a citação / substituição de caracteres não imprimíveis; @Kusalananda, o seu lsnão é compatível com POSIX, se ainda o fizer). lsa saída já está classificada. Portanto, canalizá-lo para sort, na melhor das hipóteses, não fazer nada e, na pior das hipóteses, alterar a saída (se os nomes dos arquivos contiverem caracteres de nova linha) ou falhar em nomes de arquivos que não sejam texto. ls -a | catseria melhor. Ou melhor ainda ls -A1, como já mencionado (e porque você geralmente não quer que as substituições / citando quando exibido em um terminal)
— Stéphane Chazelas

1
@ StéphaneChazelas Observado. lsse comporta de maneira diferente quando a saída não é um terminal.
— Kusalananda

3

Você não pode analisar a saída de ls, muito menos ls -lporque a nova linha, assim como o espaço é um caractere tão válido quanto qualquer outro em um nome de arquivo. Além disso, você precisará considerar links simbólicos com saída semelhante ... foo -> bar.

Por que você usaria de -lqualquer maneira se você deseja apenas o nome do arquivo?

Apenas faça:

for file in *; do
  ...
done

Se você deseja incluir arquivos de ponto (exceto .e ..), dependendo do shell:

zsh:

for file in *(ND); do
  ...
done

bash:

shopt -s nullglob dotglob
for file in *; do
  ...
done

ksh93:

FIGNORE='@(.|..)'
for file in ~(N)*; do
  ...
done

POSIXly:

for file in .[!.]* ..?* *; do
  [ -e "$file" ] || [ -L "$file" ] || continue
  ...
done


1
ls -Al | tr -s ' ' | cut -f9- -d' '

compactar vários espaços em espaços únicos com tr, você pode usar recortar para dividir nos campos




-1
ls --file *|grep ^ 

exibe quais arquivos em qual diretório.


Não acho que isso resolva a questão.
— Jeff Schaller
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.