Lista solo los archivos normales (pero no los directorios) en el directorio actual

126

Puedo usar ls -ld */para enumerar todas las entradas del directorio en el directorio actual. ¿Existe una manera igualmente fácil de enumerar todos los archivos normales en el directorio actual? Sé que puedo usar find

find . -maxdepth 1 -type f

o stat

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

pero esto no me parece demasiado elegante. ¿Hay una manera breve y agradable de enumerar solo los archivos normales (no me interesan los dispositivos, las tuberías, etc.) pero no los subdirectorios del directorio actual? Enumerar enlaces simbólicos también sería una ventaja, pero no es una necesidad.

daniel kullmann
fuente
55
¿Qué quieres decir con "demasiado elegante"? Hasta donde yo sé, el findcomando es la mejor manera de hacer lo que quieres. ¡Para algunas otras opciones confiables, debe buscar comandos específicos de shell (y esos son cualquier cosa menos portátiles)!
rahmu
@rahmu Yo estaba por algo similar ls -d */, que es corto, fácil de escribir y fácil de entender. Así que estoy bastante contento con la respuesta de Ulrich Dangel, aunque no estoy usando zsh.
daniel kullmann

Respuestas:

32

Con zshy Glob Qualifiers puede expresarlo fácilmente directamente, por ejemplo:

echo *(.)

solo devolverá la lista de archivos normales o un error dependiendo de su configuración.

Para los no directorios:

echo *(^/)

(incluirá enlaces simbólicos (incluidos los directorios), tuberías con nombre, dispositivos, enchufes, puertas ...)

echo *(-.)

para archivos regulares y enlaces simbólicos a archivos regulares.

echo *(-^/)

para no directorios y tampoco enlaces simbólicos a directorios.

Además, vea el Dcalificador global si desea incluir archivos D ot (archivos ocultos), como *(D-.).

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

Este comando enumera todos los archivos no ocultos que no son directorios (archivos normales, enlaces, archivos de dispositivo , etc.). Para incluir también archivos ocultos, agregue la -Aopción als

Se supone que ninguno de los archivos tiene caracteres de nueva línea en su nombre. Agregar una -qopción a lstransformaría todos los caracteres no imprimibles, incluida la nueva línea ?, para garantizar que estén en una línea y sean tan adecuados para alimentar a una utilidad basada en líneas como grepe imprimir en una terminal.

Athul Biju
fuente
14
+1, esta es una buena respuesta. La votación negativa de un nuevo usuario sin comentarios es bastante impactante para mí, especialmente cuando se proporciona una respuesta funcional. El único caso marginal que puedo ver donde esto no funcionará correctamente es si hay una nueva línea en un nombre de archivo. También retener los colores sería una buena adición cuando sea compatible. Para GNU puede agregar --color=alwaysa ls, para OSX -G.
Graeme
Hola, el comando que ha dado es excelente y ciertamente me ayuda, sin embargo, me preguntaba si es posible usar el comando anterior y cambiar el permiso de archivo al mismo tiempo. Intenté agregar sudo chmod 777al final, y recibí errores ... Cualquier ayuda es muy apreciada
dissidia
3
Si también desea excluir enlaces simbólicos que apuntan a directorios, haga ls -pL | grep -v /. Los -Lenlaces simbólicos de desreferencia añadidos .
Matthias Braun
1
Si también te gusta usar el filtro comodín, hazlo ls -pdL something* | grep -v /. La -dopción agregada enumera los directorios, no sus contenidos, por lo que se excluirán correctamente.
Rockallite
Y si desea obtener todos los archivos sin carpetas, simplemente elimine -v
jasonleonhard el
23

Para enumerar solo archivos normales:

ls -al | grep '^-'

Con enlaces simbólicos (a cualquier tipo de archivo) incluidos:

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

Donde el primer carácter de la lista describe el tipo de archivo, -significa que es un archivo normal, ya que el enlace simbólico es l.

Debian / Ubuntu

Imprima los nombres de todos los archivos coincidentes (incluidos los enlaces):

run-parts --list --regex . .

Con caminos absolutos:

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

Imprima los nombres de todos los archivos /etcque comienzan con py terminan con d:

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

lsno tiene ninguna opción para hacer eso, pero una de las cosas buenas de unix y linux es que las tuberías largas y poco elegantes pueden convertirse fácilmente en un script, función o alias de shell. y estos, a su vez, pueden usarse en tuberías como cualquier otro programa.

(NOTA: existen algunos problemas de alcance con las funciones y los alias. Los scripts están disponibles para cualquier ejecutable que pueda leerlos y ejecutarlos. Los alias y las funciones solo están disponibles en el shell actual, aunque el .profile / .bashrc, etc. de un sub-shell puede redefinir y así ponerlos a disposición. Además, se puede escribir un script en cualquier idioma, incluidos bash / sh, awk, perl, python y otros, el que sea mejor para el trabajo o con el que esté más familiarizado)

p.ej

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

He agregado xargs para que pueda usar todas las lsopciones habituales , p. Ej.lsf -lrS

Debido a que usa find, se mostrarán todos los archivos de puntos normalmente ocultos, y todos los nombres de archivo tendrán el prefijo ./, esa es la única diferencia que notará.

Podría excluir archivos de puntos con, ! -iname '.*'pero luego tendría que tener dos versiones del alias: una que mostrara archivos de puntos y otra que no.

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

Alternativamente, si lsffuera un script en lugar de un alias, podría analizar las opciones (tal vez con getopts o / usr / bin / getopt o similar), y excluir los archivos de puntos a menos que -aestuvieran presentes.

cas
fuente
-namees suficiente, no necesitas -iname.
Totor
8
bash-4.2$ ls -F | grep -v '[/@=|]$' | more

La opción -F para ls agrega * a ejecutables, / a directorios, @ a enlaces simbólicos, = a sockets y | a FIFOs. Luego puede usar grep para excluir los caracteres de archivo no regulares de la salida y usted tiene los archivos. Esto funcionará en cualquier shell, no solo en zsh.

Las debilidades son:

  1. Cualquier archivo cuyo nombre termina en @, =o |será excluido (pero que en realidad no debería tener archivos con esos caracteres en el nombre de todos modos)
  2. Eso no excluye los archivos del dispositivo o algunos tipos exóticos de archivos en algunos sistemas como puertas.
  3. Tendrá un asterisco agregado en cualquier archivo que sea ejecutable. Eso podría manejarse canalizando a través de sed para eliminar cualquier carácter '*' de la salida.
  4. Eso no funciona correctamente si hay nombres de archivo que contienen caracteres de nueva línea.
kurtm
fuente
En el sistema que estoy escribiendo esto en el 10% de los archivos tienen nombres que contienen =, @o |caracteres. =es común en nombres de archivos o maildir que tienen una base codificada imprimible con base64 o entre comillas. @en definiciones locales, para direcciones de correo electrónico y más. Sin embargo, es raro que aparezcan al final del nombre del archivo. (solo 31 de 2.2 millones en este sistema, por ejemplo)
Stéphane Chazelas
3

El manual establece que la opción 'f' está solo en contra de 'archivo normal', no en tuberías, zócalos o dispositivos block / char, lo que significa que ya está haciendo lo correcto.

   -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)
margarita
fuente
0

Esto no es particularmente corto, pero puede convertirlo en un script o un alias si necesita llamarlo rápidamente. Usando el comando ls como una matriz de entrada, llame a ls -ld en cada entrada canalizada a grep para excluir directorios con la salida enviada a nulo, y si tiene éxito, repita la entrada original:

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

Puede invertir el grep y la salida condicional, los mismos resultados:

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

Este es un hilo un poco viejo, pero la forma más limpia de listar solo archivos.

ls -al | grep '^-' | awk '{print $9}'
RJ
fuente
1
touch "some file name"para ver un contraejemplo rápido
Jeff Schaller
@JeffSchaller Tienes un punto válido. Por eso algo como esto. ls -al | grep '^-' | awk '{ for(i=9; i<=NF; ++i) printf $i""FS; print "" }', debe manejar los archivos con espacios en ellos.
RJ