Encontrar el archivo más grande de forma recursiva

41

Estoy tratando de encontrar el archivo más grande en un directorio de forma recursiva. Si hay un subdirectorio dentro de ese directorio, la función debe ir dentro de ese directorio y verificar si el archivo más grande está allí. Una vez que se encuentra el archivo más grande, la salida se muestra con el nombre de la ruta relativa y el nombre y el tamaño del archivo más grande.

EX:

dude@shell2 (~...assignment/solutions) % bash maxfile.sh ~/test
class/asn
dude.h.gch: 9481628

Esto es lo que tengo:

#!/bin/sh
clear

recursiveS() {
    for d in *; do
        if [ -d $d ]; then
            (cd $d; echo $(pwd)/$line; du -a; recursiveS;)
        fi
    done
}
recursiveS

He estado atrapado por un tiempo ahora. No puedo implementar esto al canalizar una serie de herramientas Unix existentes. Cualquier idea sería buena!

user2419571
fuente
stackoverflow.com/questions/12522269/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
ir en sólo subdirectorios: for d in */ .[^.]*/; do ... `
Olivier Dulac

Respuestas:

54

use find(aquí suponiendo GNU find) para generar nombres de archivo con el tamaño del archivo. ordenar. imprime el más grande.

find . -type f -printf "%s\t%p\n" | sort -n | tail -1

Eso supone que las rutas de los archivos no contienen caracteres de nueva línea.


Usando un bucle bashcon la implementación de GNU de stat:

shopt -s globstar
max_s=0
for f in **; do
  if [[ -f "$f" && ! -L "$f" ]]; then
    size=$( stat -c %s -- "$f" )
    if (( size > max_s )); then
      max_s=$size
      max_f=$f
    fi
  fi
done
echo "$max_s $max_f"

Esto será significativamente más lento que la solución de búsqueda. Eso también supone que los nombres de archivo no terminan en caracteres de nueva línea y omitirán los archivos ocultos y no descenderán a directorios ocultos.

Si hay un archivo llamado -en el directorio actual, se considerará el tamaño del archivo abierto en stdin.

Tenga en cuenta que las versiones bashanteriores a 4.3 seguían enlaces simbólicos al descender el árbol de directorios.

Glenn Jackman
fuente
Gracias, funciona! Agradezco la ayuda. Estoy tratando de acostumbrarme a la programación en shell. No sé mucho en este momento, así que agradezco que me digas lo que está sucediendo con esa línea de código.
user2419571
Pregunta rápida: Por curiosidad, ¿hay alguna manera de hacerlo sin comandos de canalización? Tengo curiosidad porque cada ejemplo que he visto ha utilizado tuberías de algún tipo.
user2419571
2
Estoy seguro de que hay otras formas de hacerlo. La filosofía de UNIX es que las herramientas deben ser de un solo propósito y encadenarlas para que la salida de un comando se alimente a la entrada del siguiente.
Glenn Jackman
Eso tiene sentido. Gracias de nuevo por tu ayuda.
user2419571
2
@ user2419571:; tail -n 1 <(sort -n <(find . -type f -printf "%s\t%p\n")))
Cyrus
9

Este comando también ayuda a enumerar el tamaño definido.

find . -type f -size +100M -exec ls -lh {} \;
senthil sivasamy
fuente
5

Esto funciona en BSD / macOS:

find . -type f -ls | sort -k7 -r

También puede adjuntar | head -n 3para mostrar el número de entradas interesantes (3 en este caso).

CeDeROM
fuente
1
Esta respuesta podría mejorarse explicando cómo funciona. Además, se ve muy similar a la respuesta aceptada (que tampoco explica completamente cómo funciona).
dhag
man findy man sort, use brainz :-)
CeDeROM
Realmente no funciona en MacOS, ya que no puede devolver el tamaño correctamente y devuelve una gran cantidad de columnas.
sorin
3

Con zsh, para el archivo regular más grande:

ls -ld -- **/*(.DOL[1])

(por supuesto, puede reemplazarlo ls -ld --con cualquier comando. Si usa GNU lso compatible, consulte también la -hopción para tamaños legibles por humanos )

  • .: solo archivos normales (no directorios, enlaces simbólicos, dispositivos, fifos ...)
  • D: incluye los ocultos y desciende a directorios ocultos
  • OL: orden inverso por tamaño ( Length).
  • [1]: solo el primer partido.

Si hay empates, obtendrás cualquiera de ellos al azar. Si desea el primero en orden alfabético, agregue un extra on( order by name) para ordenar los lazos alfabéticamente.

Tenga en cuenta que considera el tamaño de los archivos, no el uso del disco.

Stéphane Chazelas
fuente
... Empiezo a creer que estás en la nómina de zsh;) (¿cuál podría ser?). Desafortunadamente, zsh no está disponible en todos los sistemas ...
Olivier Dulac
¿Posible obtener los primeros diez archivos? (Sin hacer algo estúpido como un bucle)
Wowfunhappy
1
@Wowfunhappy reemplazar [1]con[1,10]
Stéphane Chazelas