Listar apenas arquivos regulares (mas não diretórios) no diretório atual

126

Eu posso usar ls -ld */para listar todas as entradas do diretório no diretório atual. Existe uma maneira igualmente fácil de listar todos os arquivos regulares no diretório atual? Eu sei que posso usar o find

find . -maxdepth 1 -type f

ou stat

stat -c "%F %n" * | grep "regular file" | cut -d' ' -f 3-

mas isso não me parece excessivamente elegante. Existe uma maneira curta e agradável de listar apenas os arquivos regulares (não me importo com dispositivos, tubulações etc.), mas não os subdiretórios do diretório atual? Listar links simbólicos também seria uma vantagem, mas não é uma necessidade.

daniel kullmann
fonte
5
O que você quer dizer com "elegante demais"? Até onde eu sei, o findcomando é a melhor maneira de fazer o que você deseja. Para outras opções confiáveis, você deve procurar comandos específicos do shell (e esses são tudo menos portáteis)!
rahmu
@rahmu Eu fui a favor de algo parecido ls -d */, curto, fácil de digitar e fácil de entender. Então, eu estou muito feliz com a resposta de Ulrich Dangel, mesmo que não esteja usando o zsh.
Daniel kullmann 18/09/12

Respostas:

32

Com os Qualificadoreszsh e Glob, você pode expressá-lo facilmente diretamente, por exemplo:

echo *(.)

retornará apenas a lista de arquivos regulares ou um erro, dependendo da sua configuração.

Para os não diretórios:

echo *(^/)

(incluirá links simbólicos (inclusive para diretórios), tubos nomeados, dispositivos, soquetes, portas ...)

echo *(-.)

para arquivos regulares e links simbólicos para arquivos regulares.

echo *(-^/)

para não diretórios e também não possui links simbólicos para diretórios.

Além disso, consulte o Dqualificador de globbing se desejar incluir arquivos D ot (arquivos ocultos), como *(D-.).

Ulrich Dangel
fonte
170
ls -p | grep -v / 

Este comando lista todos os arquivos não ocultos que não são diretórios (arquivos regulares, links, arquivos de dispositivos etc.). Para também incluir arquivos ocultos, adicione a -Aopção als

Ele assume que nenhum dos arquivos possui caracteres de nova linha em seu nome. Adicionar uma -qopção para lstransformar todos os caracteres não imprimíveis, incluindo nova linha em ?, garantindo que eles estejam em uma linha e adequados para alimentar um utilitário baseado em linhas como grepe para imprimir em um terminal.

Athul Biju
fonte
14
+1, esta é uma boa resposta. A votação de um novo usuário sem comentários é muito chocante para mim, especialmente quando uma resposta é fornecida. O único caso em que posso ver onde isso não funcionará corretamente é se houver uma nova linha em um nome de arquivo. A retenção de cores também seria uma boa adição, quando suportada. Para o GNU, você pode adicionar --color=alwaysao ls, para OSX -G.
Graeme
Oi, o comando que você deu é ótimo e certamente me ajuda, no entanto, eu queria saber se é possível usar o comando acima e alterar a permissão do arquivo ao mesmo tempo? Eu tentei adicionar em sudo chmod 777no final, e me foi dada erros ... Qualquer ajuda é muito apreciada
Dissidia
3
Se você também gostaria de excluir links simbólicos que apontam para diretórios ls -pL | grep -v /. As -Lreferências desreferenciadas adicionam links simbólicos.
Matthias Braun
11
Se você também gosta de usar filtro curinga, faça ls -pdL something* | grep -v /. A -dopção adicionada lista os próprios diretórios, não o conteúdo, portanto eles serão excluídos corretamente.
Rockallite
E se você queria pegar todos os arquivos sem pastas basta remover o -v
jasonleonhard
23

Para listar apenas arquivos regulares:

ls -al | grep '^-'

Com links simbólicos (para qualquer tipo de arquivo) incluídos:

ls -al | grep '^[-l]'

Onde o primeiro caractere da lista descreve o tipo de arquivo, -significa que é um arquivo comum, pois o link simbólico é l.

Debian / Ubuntu

Imprima os nomes de todos os arquivos correspondentes (incluindo links):

run-parts --list --regex . .

Com caminhos absolutos:

run-parts --list --regex . "$PWD"

Imprima os nomes de todos os arquivos /etcque começam com pe terminam com d:

run-parts --list --regex '^p.*d$' /etc
kenorb
fonte
15

lsnão tem opção para fazer isso, mas uma das coisas boas sobre o unix e o linux é que pipelines inelegantes e cansativos podem ser facilmente transformados em scripts, funções ou alias de shell. e estes podem, por sua vez, ser usados ​​em pipelines como qualquer outro programa.

(OBSERVAÇÃO: existem alguns problemas de escopo com funções e aliases. Os scripts estão disponíveis para qualquer executável que possa lê-los e executá-los. Aliases e funções estão disponíveis apenas no shell atual - embora o .profile / .bashrc etc de um sub-shell possa redefinir Além disso, um script pode ser escrito em qualquer idioma - incluindo bash / sh, awk, perl, python e outros - o que for melhor para o trabalho ou com o qual você esteja mais familiarizado)

por exemplo

alias lsf='find . -maxdepth 1 -type f -print0 | xargs -0r ls'

Adicionei xargs para que você possa usar todas as lsopções usuais , por exemplolsf -lrS

Como ele usa find, todos os arquivos de ponto normalmente ocultos serão exibidos e todos os nomes de arquivos serão prefixados com ./ - essa é a única diferença que você notará.

Você pode excluir arquivos de ponto com, ! -iname '.*'mas precisará ter duas versões do alias - uma que exibisse arquivos de ponto e outra que não.

alias lsf2='find . -maxdepth 1 -type f -a ! -iname '\''.*'\'' -print0 | xargs -0r ls'

Como alternativa, se lsffosse um script em vez de um alias, você poderia analisar as opções (talvez com getopts ou / usr / bin / getopt ou similar) e excluir arquivos de ponto a menos que -aestivesse presente.

cas
fonte
-nameé suficiente, você não precisa -iname.
Totor
8
bash-4.2$ ls -F | grep -v '[/@=|]$' | more

A opção -F para ls acrescenta * a executáveis, / a diretórios, @ a links simbólicos, = a soquetes e | para FIFOs. Você pode usar o grep para excluir os caracteres de arquivo não regulares da saída e os possui. Isso funcionará em qualquer shell, não apenas no zsh.

Os pontos fracos são:

  1. Qualquer arquivo cujo nome termina em @, =ou |serão excluídos (mas você realmente não deve ter arquivos com esses caracteres no nome de qualquer maneira)
  2. Isso não exclui arquivos de dispositivos ou alguns tipos exóticos de arquivos em alguns sistemas, como portas.
  3. Você terá um asterisco anexado a qualquer arquivo executável. Isso poderia ser tratado através da canalização do sed para remover quaisquer caracteres '*' da saída.
  4. Isso não funciona corretamente se houver nomes de arquivos contendo caracteres de nova linha.
Kurtm
fonte
No sistema que estou escrevendo isso em, 10% dos arquivos têm nomes que contenham =, @ou |caracteres. =é comum em nomes de arquivos ou nomes de arquivos que possuem uma parte codificada em base64 ou imprimível entre aspas. @nas definições de localidade, para endereços de email e muito mais. É raro que eles apareçam no final do nome do arquivo. (apenas 31 dos 2,2 milhões neste sistema, por exemplo)
Stéphane Chazelas 31/07
3

O manual afirmou que a opção 'f' é apenas contra 'arquivo normal', não tubos, soquetes ou dispositivos de bloco / char, o que significa que você já está fazendo as coisas certas.

   -type c
          File is of type c:

          b      block (buffered) special

          c      character (unbuffered) special

          d      directory

          p      named pipe (FIFO)

          f      regular file

          l      symbolic link; this is never true if the -L option or the
                 -follow option is in effect, unless the symbolic link  is
                 broken.  If you want to search for symbolic links when -L
                 is in effect, use -xtype.

          s      socket

          D      door (Solaris)
margarida
fonte
0

Isso não é particularmente curto, mas você pode transformá-lo em um script ou alias se precisar chamá-lo rapidamente. Usando o comando ls como uma matriz de entrada, chame ls -ld em cada entrada canalizada para grep para excluir diretórios com a saída enviada para nula e, se bem-sucedida, ecoar a entrada original:

for list in `ls` ; do ls -ld $list | grep -v ^d > /dev/null && echo $list ; done ;

Você pode inverter a saída grep e condicional, os mesmos resultados:

for list in `ls` ; do ls -ld $list | grep ^d > /dev/null || echo $list ; done ;
Don R
fonte
\dev\null?!?!
manatwork
0

Esta é uma discussão um pouco antiga, mas a maneira mais limpa de listar apenas arquivos.

ls -al | grep '^-' | awk '{print $9}'
RJ
fonte
11
touch "some file name"para ver um rápido contra
Jeff Schaller
@JeffSchaller Você tem um ponto válido. Para isso algo assim. ls -al | grep '^-' | awk '{ for(i=9; i<=NF; ++i) printf $i""FS; print "" }', deve manipular os arquivos com espaços neles.
RJ