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.

Alex Zern
fonte
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.

terdon
fonte
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.

bahamat
fonte
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
Ben
fonte
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
Stéphane Chazelas
fonte
1

E se:

for file in * .[!.]*
do
  printf "%s\n" "$file"
done
Scrutinizer
fonte
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

simpleuser
fonte
-1
ls --file *|grep ^ 

exibe quais arquivos em qual diretório.

vars
fonte
Não acho que isso resolva a questão.
Jeff Schaller