Jak uzyskać rozmiar folderu ignorując twarde linki?


17

Używam rsnapshot do tworzenia kopii zapasowych, które generują serię folderów zawierających pliki o tej samej nazwie. Niektóre pliki są na stałe połączone, a inne są osobne. Na przykład, hourly.1/file1i hourly.2/file1mogą być twardo połączone z tym samym plikiem, podczas gdy hourly.1/file2i hourly.2/file2są całkowicie oddzielnymi plikami.

Chcę znaleźć ilość miejsca zajmowanego przez folder, hourly.2 ignorując wszystkie pliki, które są twardymi linkami do plików hourly.1. Tak więc w powyższym przykładzie chciałbym uzyskać rozmiar file2, ale zignoruj ​​file1.

Używam bash na Linuksie i chcę to zrobić z wiersza poleceń tak prosto, jak to możliwe, więc nie proszę o żadne duże rozwiązania graficzne lub inne tylko dla systemu operacyjnego.

Odpowiedzi:


7

Całkowity rozmiar w bajtach wszystkich plików, w hourly.2których znajduje się tylko jedno łącze:

$ find ./hourly.2 -type f -links 1 -printf "%s\n" | awk '{s=s+$1} END {print s}'

Ze findstrony podręcznika:

   -links n
          File has n links.

Aby uzyskać sumę w kilobajtach zamiast w bajtach, użyj -printf "%k\n"

Aby wyświetlić listę plików o różnych liczbach linków, baw się z find -links +1(więcej niż jednym linkiem), find -links -5(mniej niż pięcioma linkami) i tak dalej.


1
Jeśli plik, w którym znajduje się twardy link do pliku hourly2, polecenie wykona niewłaściwą odpowiedź.
cuonglm

@Gnouc - Cóż, tak - zależy to od tego, w jaki sposób kończą się pliki hourly.2. Jeśli zostaną tam skopiowane, nie będą miały dodatkowych linków, a moje polecenie będzie działać. Jeśli są one mocno powiązane, to oczywiście się nie powiedzie. Zakładam, że nowe pliki kopii zapasowych są kopiowane.
grebneke

11

Jeśli chcesz, aby rozmiar plików znajdujących się poniżej, hourly.2ale nie poniżej hourly.1, możesz uzyskać go nieco pośrednio du. Jeśli duprzetwarza ten sam plik więcej niż jeden raz (nawet pod różnymi nazwami, tj. Twardymi linkami), zlicza ten plik tylko za pierwszym razem. Więc to, czego dotyczy du hourly.1 hourly.2raport, hourly.2to rozmiar, którego szukasz. A zatem:

du -ks hourly.1 hourly.2 | sed -n '2s/[^0-9]*//p'

(Działa na każdym systemie POSIX i większości innych wariantów Uniksa. Zakłada, że ​​nazwa katalogu hourly.1nie zawiera żadnego nowego wiersza).


Z jakiegoś dziwnego powodu du nie zawsze zauważa twarde pliki na RHEL5 - jeśli zrobię „du -sh dir / sub dir”, wyjście dla dir jest takie samo, jak gdybym właśnie powiedział „du -sh dir” - nie wykluczając rozmiaru z „dir / sub”.
Andreas Krey

9

Jak mówi @Gilles, ponieważ duliczy tylko pierwsze hardlinks wskazujące na ten sam i-węzeł, który napotyka, możesz nadać mu katalogi z rzędu:

$ du -hc --max-depth=0 dirA dirB
29G /hourly.1
 1G /hourly.2
30G total

Oznacza to, że dowolny plik w „hourly.2” odwołujący się do i-węzła (inaczej „prawdziwy” plik) już wymieniony w „hourly.1”, nie będzie liczony.


2
Według du --help opcja --max-depth = 0 jest równoważna -s , więc powyżej można skrócić jako:$ du -hcs dirA dirB
akavel

2

Prościej

du -hc --max-depth=1 path/

Przykład

9.4G    daily/users/rockspa/home/daily.21
3.6G    daily/users/rockspa/home/daily.30
4.2G    daily/users/rockspa/home/daily.11
1.1G    daily/users/rockspa/home/daily.4
4.2G    daily/users/rockspa/home/daily.9
3.0G    daily/users/rockspa/home/daily.25
3.5G    daily/users/rockspa/home/daily.20
4.2G    daily/users/rockspa/home/daily.13
913M    daily/users/rockspa/home/daily.5
2.8G    daily/users/rockspa/home/daily.26
1.4G    daily/users/rockspa/home/daily.1
2.6G    daily/users/rockspa/home/daily.28
4.2G    daily/users/rockspa/home/daily.15
3.8G    daily/users/rockspa/home/daily.19
327M    daily/users/rockspa/home/daily.8
4.2G    daily/users/rockspa/home/daily.17
3.1G    daily/users/rockspa/home/daily.23
...

Dzięki, Abdel. To powinna być zaakceptowana odpowiedź.
TiberiusKirk,

Niesamowite. Działa to dla mnie przy pierwszej próbie na moim systemie macOS 10.15. Dziękuję Ci.
dimitarvp

1

Niesamowicie kompilacje BusyBox findpochodzą bez -printfwsparcia. Oto modyfikacja odpowiedzi @ grebneke :

find . -type f -links 1 -exec ls -l {} \;| awk '{s=s+$5} END {print s}'
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.