Znajdowanie rekurencyjnie największego pliku


41

Próbuję rekurencyjnie znaleźć największy plik w katalogu. Jeśli w tym katalogu znajduje się podkatalog, funkcja musi wejść do tego katalogu i sprawdzić, czy jest tam największy plik. Po znalezieniu największego pliku wyświetlane są dane wyjściowe z względną nazwą ścieżki oraz nazwą i rozmiarem największego pliku.

DAWNY:

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

Oto co mam:

#!/bin/sh
clear

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

Utknąłem na chwilę. Nie mogę tego zaimplementować, potokując wiele istniejących narzędzi uniksowych. Wszelkie pomysły byłyby fajne!



aby przejść w ciągu zaledwie subdirs: for d in */ .[^.]*/; do ... '
Olivier Dulac

Odpowiedzi:


54

użyj find(tutaj zakładając GNU find), aby wyprowadzić nazwy plików o rozmiarze pliku. sortować. wydrukuj największy.

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

Zakłada się, że ścieżki do plików nie zawierają znaków nowej linii.


Używanie pętli w bashimplementacji GNU 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"

Będzie to znacznie wolniejsze niż rozwiązanie wyszukiwania. Zakłada to również, że nazwy plików nie kończą się na znakach nowego wiersza i pomijają ukryte pliki i nie schodzą do ukrytych katalogów.

Jeśli -w bieżącym katalogu jest plik wywołany, zostanie wzięty pod uwagę rozmiar pliku otwartego na standardowym wejściu.

Uwaga: wersje z wersji bashwcześniejszej niż 4.3 korzystały z dowiązań symbolicznych podczas zejścia z drzewa katalogów.


Dzięki, działa! Doceniam pomoc. Próbuję przyzwyczaić się do programowania w powłoce. Obecnie niewiele wiem, więc doceniam to, że mówisz mi, co się dzieje z tym wierszem kodu.
user2419571,

Szybkie pytanie: z ciekawości istnieje sposób, aby to zrobić bez komend potokowych? Jestem ciekawy, ponieważ każdy przykład, który widziałem, wykorzystywał pewnego rodzaju orurowanie.
user2419571,

2
Jestem pewien, że są na to inne sposoby. Filozofią UNIXa jest to, że narzędzia powinny być jednocelowe i łączyć je ze sobą, aby dane wyjściowe jednego polecenia były podawane do danych wejściowych następnego.
glenn jackman

To ma sens. Jeszcze raz dziękuję za pomoc.
user2419571

2
@ user2419571:; tail -n 1 <(sort -n <(find . -type f -printf "%s\t%p\n")))
Cyrus

9

To polecenie pomaga również wyświetlić zdefiniowany rozmiar.

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

5

Działa to na BSD / macOS:

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

Możesz także dołączyć | head -n 3liczbę interesujących wpisów (w tym przypadku 3).


1
Odpowiedź można poprawić, wyjaśniając, jak to działa. Wygląda również bardzo podobnie do zaakceptowanej odpowiedzi (która nie wyjaśnia w pełni, jak to działa).
dhag

man findi man sortużyj brainz :-)
CeDeROM

Naprawdę nie działa na MacOS, ponieważ nie zwraca poprawnie rozmiaru i zwraca ogromną liczbę kolumn.
sorin,

3

Z zsh, dla największego zwykłego pliku:

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

(oczywiście możesz zastąpić ls -ld --dowolną komendą. Jeśli używasz GNU lslub kompatybilnego, zobacz także -hopcję rozmiarów czytelnych dla człowieka )

  • .: tylko zwykłe pliki (nie katalogi, dowiązania symboliczne, urządzenia, fifos ...)
  • D: dołącz ukryte i zejdź do ukrytych katalogów
  • OL: odwrotnie sortowane według rozmiaru ( Length).
  • [1]: tylko pierwszy mecz.

Jeśli są remisy, otrzymasz dowolną z nich losowo. Jeśli chcesz pierwszy w kolejności alfabetycznej, dodaj dodatkowy on( order by name), aby posortować więzi alfabetycznie.

Pamiętaj, że bierze pod uwagę rozmiar plików, a nie użycie dysku.


... Zaczynam wierzyć, że jesteś na liście płac Zsh;) (co może być bardzo dobrze?). zsh niestety nie jest dostępny we wszystkich systemach ...
Olivier Dulac

Można uzyskać pierwsze dziesięć plików? (Bez robienia czegoś głupiego jak pętla)
Wowfunhappy

1
@Wowfunhappy zastąpić [1]z[1,10]
Stéphane Chazelas
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.