Lista de archivos ordenados por la cantidad de líneas que contienen

32

¿Cómo puedo enumerar la cantidad de líneas en los archivos /group/book/four/word, ordenadas por la cantidad de líneas que contienen?

ls -l el comando los enumera pero no los ordena

Ken R
fuente
1
¿Desea que los archivos se enumeren por número de líneas, o enumere el número de líneas en los archivos o ambos? ls -lno da el número de líneas. ls -lSordena el archivo por tamaño con algunas lsimplementaciones (el tamaño es el número de bytes en el contenido).
Stéphane Chazelas

Respuestas:

34

Deberías usar un comando como este:

find /group/book/four/word/ -type f -exec wc -l {} + | sort -rn
  • find: busca archivos en la ruta que deseas. Si no desea que sea recursivo y su findimplementación lo admite, debe agregarlo -maxdepth 1justo antes de la -execopción.
  • exec: le dice al comando que se ejecute wc -len cada archivo.
  • sort -rn: ordena los resultados numéricamente en orden inverso. De mayor a menor.

(que supone que los nombres de archivo no contienen caracteres de nueva línea).

jherran
fuente
Tenga en cuenta que cuando pasa más de un archivo (o con algunas implementaciones, más de un archivo que puede leer), wctambién imprimirá una totallínea, por lo que aquí también obtendrá una o más líneas "totales" a menos que solo haya un archivo . Puede canalizar grep /para eliminarlos.
Stéphane Chazelas
voto positivo por sortorden
Francisco
¿Cómo puedo filtrar para mostrar solo el archivo con un mínimo de líneas X (excluir X = 0 línea por ejemplo)?
Matriz
11

No recursivo

Probablemente la versión más simple si no necesita recursividad:

wc -l /group/book/four/word/*|sort -n

wccuenta líneas (opción -l) en cada (pero oculto) ( *) archivos debajo /group/book/four/word/, y sortordena el resultado (a través de la tubería |) numéricamente (opción -n).

Recursivo

Alguien hizo un comentario a esta respuesta mencionando grep -rlc, antes de suprimirla. De hecho, grepes una gran alternativa, especialmente si necesita recursividad:

grep -rc '^' /group/book/four/word/|tr ':' ' '|sort -n -k2

contará (opción -c) recursivamente (opción -r) líneas que coinciden ( grep) '^'(es decir, principio de líneas) en el directorio /group/book/four/word/. Luego debe reemplazar los dos puntos por un espacio, por ejemplo, usando tr, para ayudar sort, que desea ordenar numéricamente (opción -n) en la segunda columna (opción -k2).

Actualización: Vea el comentario de Stephane sobre posibles limitaciones y cómo puede deshacerse de él tr.

Skippy le Grand Gourou
fuente
3
grep -c .cuenta las líneas que contienen al menos un carácter válido. Use grep -c '^'para contar todas las líneas (también contará los caracteres finales después de la última línea nueva con algunas grepimplementaciones). Tenga en cuenta que no todas las grepimplementaciones admiten -ray el comportamiento varía entre los que lo hacen. No necesita traducir :s (dos puntos, no punto y coma) a espacios para sort. Solo úsalo -t:. Tenga en cuenta que eso supone que los nombres de archivo no contienen :caracteres en blanco o de nueva línea.
Stéphane Chazelas
1
Gracias por publicar su solución no recursiva; No sabía que wcdaría un total tan útil si pasas por varios caminos. Acoplando esa funcionalidad con el comodín y la tubería sortestá realmente limpio.
Qcom
7

Con zsh:

lines() REPLY=$(wc -l < $REPLY)
printf '%s\n' /group/book/four/word/*(.no+lines)

Definimos una nueva función de clasificaciónlines que responde con el número de líneas en el archivo. Y usamos el o+linescalificador glob que junto con n(para ordenamiento numérico), define cómo se ordenan los resultados del glob. ( .también agregado para verificar solo los archivos normales).

Eso no supone qué carácter pueden contener los nombres de archivo que no sean los archivos ocultos (los que comienzan con .) se omiten. Agregue el Dcalificador glob si también los quiere.

Stéphane Chazelas
fuente
2
OP está etiquetado con bashsolo ...
l0b0
77
@ l0b0 eso no significa que la próxima persona que lo necesite también ejecutará bash.
terdon
4

No especifica si también desea los archivos en cualquier subdirectorio de /group/book/four/word. La findsolución en la respuesta de jherran descenderá a subdirectorios. Si eso no se desea, use el shell en su lugar:

for file in ./*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Si los nombres de sus archivos pueden contener nuevas líneas, puede usar algo como:

for file in ./*; do 
    [ -f "$file" ] && 
        printf "%lu %s\0" "$(wc -l < "$file")" "$file"
done | sort -zn | tr '\0' '\n'

Por último, si hace falta descender en subdirectorios, puede utilizar esto en bash4 o superior:

shopt -s globstar
for file in ./**/*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

Tenga en cuenta que las versiones bashanteriores a 4.3 seguían enlaces simbólicos cuando descendían recursivamente el árbol de directorios (como zsh's o tcsh' s ***/*).

Además, todas las soluciones anteriores ignorarán los archivos ocultos (aquellos cuyo nombre comienza con a ., se usan shopt -s dotglobpara incluirlos) y también incluirán el recuento de líneas de enlaces simbólicos (que el findenfoque no incluirá).

terdon
fuente
Tenga en cuenta que otras diferencias con la solución de jherran es que la suya también considerará el enlace simbólico a los archivos normales ( -xtype fen GNU find o *(-.)en zsh) y omitirá los archivos ocultos.
Stéphane Chazelas
@ StéphaneChazelas gracias, aclaró. ¿Por qué el %luen printf? Según recuerdo, eso significa un decimal largo sin signo, ¿es realmente necesario? ¿Por qué no tratar el número como una cadena? ¿Hace alguna diferencia?
terdon
2
Si la salida de wc está vacía (por ejemplo, porque el archivo no es legible), eso se expandirá en 0lugar de la cadena vacía, lo cual es un poco mejor. Algunas implementaciones de ordenación funcionan con enteros sin signo, algunas con signo. %luSuena como la apuesta más segura, pero probablemente no importa como si tuvieras 2^31líneas, de todos modos tomará años.
Stéphane Chazelas
1

Si desea instalar fdun buscador de archivos realmente rápido escrito en Rust (debe instalarlo, es genial tenerlo de todos modos)

fd --type=file . | xargs wc -l | sort -n

Básicamente fdenumera los archivos, xargs pasará la lista de archivos wc(representa el recuento de palabras, pero pasar -l hará que cuente las líneas) y finalmente se ordenará del menor número de líneas al mayor uso sort -n.

JustGage
fuente