Cómo enumerar archivos sin directorios y filtrar por nombre (opciones ls)

42

Tengo un directorio llamado uploads. Contiene un montón de archivos, además de algunos subdirectorios que a su vez contienen archivos.

¿Hay alguna manera de que pueda (en un solo paso) hacer lo siguiente:

  1. Enumere SOLAMENTE los archivos en el directorio de cargas raíz: no quiero ver los nombres de las subcarpetas ni sus contenidos;

    y

  2. NO enumere ningún archivo que comience con t_

Sé acerca de la -dbandera, pero no me da lo que quiero.

EmmyS
fuente

Respuestas:

53

Esto suena como un trabajo para find.

  • Se usa -maxdepthpara devolver solo el directorio actual, no para buscar recursivamente dentro de subcarpetas
  • Úselo -type fpara devolver solo archivos y no directorios o nodos de dispositivos o cualquier otra cosa
  • Use una combinación si -noty -namepara evitar los archivos con nombres que no desea

Podría venir así:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'
Caleb
fuente
¡Gracias! Soy bastante nuevo en CLI y nunca antes había usado find. Definitivamente voy a investigar más a fondo.
EmmyS 01 de
2
@EmmyS: Puede encontrar un pequeño truco más útil aquí. @Gilles mencionó usar -exec ls -lG -- {} +en su respuesta para obtener la salida usando opciones adicionales para ls. También puede agregar solo un -lsa este hallazgo para obtener una aproximación rápida y sucia de la vista detallada de ls.
Caleb
18

GNU ls (es decir, el comando ls en sistemas Linux no integrados y Cygwin, también disponible en algunos otros dispositivos) tiene una opción para ocultar algunos archivos, en función de sus nombres. Sin embargo, no hay forma de ignorar los directorios.

ls --hide='t_*' uploads

Otro enfoque es hacer que su shell haga la correspondencia. Bash, ksh y zsh tienen un patrón de negación !(t_*)para que coincida con todos los archivos, excepto los que coinciden t*; en bash, esta característica debe shopt -s extglobactivarse y en zsh debe activarse con setopt ksh_glob. Zsh también tiene la sintaxis equivalente con la ^t_*que debe activarse setopt extended_glob. Esto todavía no ignora los directorios. Zsh tiene una característica adicional que permite hacer coincidir archivos no solo por nombre sino también por metadatos y más: calificadores globales . Agregue (.)al final de una coincidencia para restringir a los archivos normales. La negación ^es parte de la sintaxis de coincidencia de nombres, por lo que ^t_*(.)significa "todos los archivos normales no coinciden t_*" y no "todos los archivos que no coinciden con los archivos normales t_*".

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Si te encuentras sin herramientas avanzadas, puedes hacerlo en cualquier Unix con find. No es el tipo de cosa que normalmente escribiría en la línea de comando, pero es potente y preciso. Caleb ya ha mostrado cómo hacer esto con GNU find . La -maxdepthopción no es portátil; puede usar -pruneen su lugar, para evitar que se repita findde forma portátil.

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Reemplace -printpor -exec ls -lG -- {} +para ejecutar lscon sus opciones favoritas en los archivos.

Todos los comandos anteriores ocultan archivos de puntos (es decir, archivos cuyo nombre comienza con a .). Si desea mostrar ellos, pasar -Aa ls, o añadir el Dcalificativo pegote en zsh ( ls uploads/^t_*(.D)). Con find, puede usar un enfoque diferente para hacer que se repita solo un nivel ( findno trata los archivos de puntos especialmente). Esto solo funciona completamente si se ejecuta finden el directorio actual.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print
Gilles 'SO- deja de ser malvado'
fuente
3
¿Tiene un día de trabajo? ;-) Estoy constantemente asombrado por la longitud y el nivel de detalles de sus respuestas, ¡incluso las preguntas más simples aquí en Unix SE! .. ¡Sigue así de todos modos! :)
alex
¡Gracias! Gran detalle. No sé si tengo "herramientas avanzadas" o no en este momento; Estoy en una Mac en el trabajo (aunque Linux en casa, así que estoy seguro de que esto será útil en algún momento).
EmmyS
@EmmyS: Para su caja de Linux, mi uso -maxdepthdebería funcionar, pero el problema de "portabilidad" al que se refiere Gilles es que el BSD find(también se encuentra en OSX, creo) es un animal un poco diferente, por lo que es posible que necesite su respuesta también. @Gilles: ¡+1 para el truco zsh!
Caleb
1
@Gilles: Me prunevienen a la mente algunos comentarios no tan jugosos acerca de s, pero lo dejaré pasar simplemente diciendo que cuando estoy hurgando en mis propios sistemas la cantidad de veces que el pensamiento "funcionaría este comando si estuviera encendido AIX, Solaris o MINIX3 "es aproximadamente ... en espera ... Me está costando mucho leer el medidor ... la pantalla está congelada 0.00.
Caleb
2
¿No lstiene Gnu una --use-telepathyopción? Esa es la forma más rápida de mostrar solo los archivos que desea. Sin embargo, puede que no sea portátil.
dubiousjim
8
ls -l /folder | grep ^- | awk '{print $9}'
Krayher
fuente
¿Qué hay $9en esta declaración?
EmmyS
3
@EmmyS Significa el noveno campo / columna de la salida. Esta respuesta está tratando de analizar la lssalida .
jw013
print $ NF` sería mejor, IMO. $ NF significa número de campos, que serían 9 y es un uso común en AWK como una buena oportunidad para enseñar a otros sobre $ NF.
Elijah Lynn el
1
ls -l | grep -v ^d | grep name$
RICARDO MARMOLEJO GARCIA
fuente
¿Qué haría preferible esta solución (que requiere múltiples comandos y tuberías) find?
HalosGhost
Es conciso, fácil de leer y cumple con la convención de comandos ls. Me resulta más fácil de recordar que los argumentos del comando find. A cada uno lo suyo y felicitaciones por las opciones!
tkjef
0

Déjame darle una oportunidad usando lsy tuberías:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

digamos que la última columna es la novena.

Y0NG
fuente
1
¿Qué pasa si hay archivos con espacios?
jordanm
0

Si el problema de portabilidad -maxdepth de find es un problema, puede usar:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

No soy un experto, pero creo que esto debería funcionar. Supongo que parece un poco críptico, pero si hablas mal, en realidad no lo es. $ NF podría usarse en lugar de $ 9. También puedes hacer:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

que hace lo mismo (pero quizás menos eficientemente que el anterior ???).

En realidad, después de pensar en las otras publicaciones, parece que

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

Es una forma aún más corta y clara.

Alguien por favor corrígeme si me equivoco. :-)

kkaszub
fuente
Analizar lsgeneralmente no es una buena idea . Sus trucos awk fallarán con nombres de archivos con espacios en blanco en ellos, por ejemplo.
Mat
@mat: gracias por la corrección. Después de leer el artículo que usted (y jw013) señalaron, veo que no se puede confiar en ls para generar los nombres de archivo correctos. Incluso si tuviera que reescribir el código awk para imprimir todo, desde $ 9 hasta el final de la línea (para incluir espacios en blanco), esta salida de ls aún puede ser errónea. Esto es decepcionante y debe corregirse en la OMI. Gracias de nuevo.
kkaszub
0

Encontré estas formas cortas:

ls -p uploads | grep -Ev '/'

o

ls -pIt_* uploads | grep -v /
Radu Rădeanu
fuente
-1

Prueba este alias y úsalo:

alias l='ls -hLlF'
Granular
fuente
ls -hLlFmuestra los subdirectorios y muestra los archivos que comienzan con t_. Entonces, ¿cómo responde esto a la pregunta?
Raphael Ahrens
Quizás entendí mal la pregunta. ls -hLlF no mostrará los directorios de destino de los directorios vinculados.
Granular
Parece tan. ¿Pero no has leído las otras respuestas a la pregunta?
Raphael Ahrens
-1

Pan comido:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d

Cavador
fuente
(1) Esta respuesta es tan fácil que se ha dado antes. (2) ¿Por qué cree que necesita especificar la ruta completa al directorio?
Scott
@Scott: esta es una forma muy rápida y sencilla de llegar a la solución. Se especificó la ruta completa para que la respuesta sea universal ...
Digger