Bagaimana saya bisa mengurutkan output du -h berdasarkan ukuran


967

Saya perlu mendapatkan daftar du keluaran yang dapat dibaca manusia.

Namun, dutidak memiliki opsi "urutkan berdasarkan ukuran", dan perpipaan untuk sorttidak berfungsi dengan bendera yang dapat dibaca manusia.

Misalnya, menjalankan:

du | sort -n -r 

Menghasilkan penggunaan disk yang disortir berdasarkan ukuran (menurun):

du |sort -n -r
65108   .
61508   ./dir3
2056    ./dir4
1032    ./dir1
508     ./dir2

Namun, menjalankannya dengan bendera yang dapat dibaca manusia, tidak mengurutkan dengan benar:

du -h | sort -n -r

508K    ./dir2
64M     .
61M     ./dir3
2.1M    ./dir4
1.1M    ./dir1

Adakah yang tahu cara menyortir du -h berdasarkan ukuran?


Heh ... Lucu Anda harus bertanya, karena ini telah mengganggu saya selama ... setidaknya lebih dari setahun. Minggu lalu saya mengunduh kode tersebut ke GNU coreutils (yang jenisnya merupakan bagian), dan telah melihatnya, tetapi memutuskan bahwa akan memakan waktu sedikit lebih banyak daripada waktu yang saya miliki untuk menambal ... Siapa saja? :)
bersantai

Inilah pertanyaan terkait: serverfault.com/q/737537/35034
cregox

Pernahkah Anda melihat yang ini? unix.stackexchange.com/questions/4681/… Ini adalah duplikat dekat dan bernilai emas. Anda melakukan hal yang normal dutetapi menambahkan -h ke sortperintah. Anda dapat menambahkan -rhsehingga yang terbesar adalah yang pertama di dalam file, jika tidak, Anda harus tailmelihat space hogs.
SDsolar

Saya tidak berharap pertanyaan seperti itu menjadi sangat populer ketika saya mencari di Google.
Mateen Ulhaq

Jawaban:


1363

Pada GNU coreutils 7.5 dirilis pada Agustus 2009, sortmemungkinkan -hparameter, yang memungkinkan sufiks numerik dari jenis yang dihasilkan oleh du -h:

du -hs * | sort -h

Jika Anda menggunakan jenis yang tidak mendukung -h, Anda dapat menginstal GNU Coreutils. Misalnya pada Mac OS X yang lebih lama:

brew install coreutils
du -hs * | gsort -h

Dari sort manual :

-h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)


3
Bagian yang relevan dari manual ini: gnu.org/software/coreutils/manual/…
wodow

29
Mudah untuk menginstal pada OS X dengan homebrew - buatan install coreutils.
Richard Poirier

41
Bagus Secara pribadi saya selalu melakukannya du -BM | sort -nrsebagai solusi - itu cukup mudah dibaca oleh manusia, dan disortir, jika ada yang terjebak dengan coreutil yang lebih tua.
chutz

30
Jika menggunakan OSX via Homebrew, perhatikan bahwa Anda sekarang harus menggunakan gsort daripada mengurutkan:du -hs * | gsort -h
Brian Cline

2
@ PaulDraper, du -BMmencetak semuanya dalam megabita, sehingga file yang 168K sebenarnya akan ditampilkan sebagai 0M. Kecuali ada beberapa perbedaan versi yang tidak saya sadari. Versi saya duhanya menunjukkan nilai megabyte integer.
chutz

88
du | sort -nr | cut -f2- | xargs du -hs

48
Dan itu akan melakukan penghitungan duplikat dalam jumlah besar.
Douglas Leeder

1
Pertama ia melakukan du - kemudian untuk setiap entri itu menghitung ulang ukuran hanya untuk mencetaknya dalam bentuk yang dapat dibaca manusia.
Douglas Leeder

8
@Douglas Leeder: Anda tepat untuk penghitungan duplikat, tetapi berpikir bahwa du kedua tidak dimulai dari cache dingin (terima kasih ke OS) @hasen j: xargs adalah perintah yang sangat berguna, ia membagi stdinnya dan memberinya sebagai argumen ke perintah yang diberikan
cadrian

4
Chris sebenarnya lebih unggul karena bekerja dengan jalur yang berisi spasi putih. Melontar dengan suara Anda, sobat.
rbright

3
Jelek, tapi lintas platform :).
voretaq7

62

@Douglas Leeder, satu jawaban lagi: Urutkan output yang dapat dibaca manusia dari du -h menggunakan alat lain. Seperti Perl!

du -h | perl -e 'sub h{%h=(K=>10,M=>20,G=>30);($n,$u)=shift=~/([0-9.]+)(\D)/;
return $n*2**$h{$u}}print sort{h($b)<=>h($a)}<>;'

Bagi menjadi dua garis agar sesuai dengan tampilan. Anda dapat menggunakannya dengan cara ini atau menjadikannya one-liner, itu akan berfungsi baik.

Keluaran:

4.5M    .
3.7M    ./colors
372K    ./plugin
128K    ./autoload
100K    ./doc
100K    ./syntax

EDIT: Setelah beberapa putaran bermain golf di PerlMonks , hasil akhirnya adalah sebagai berikut:

perl -e'%h=map{/.\s/;99**(ord$&&7)-$`,$_}`du -h`;die@h{sort%h}'

2
Versi singkat Anda aktif stderrkarena dieAnda dapat mengubahnya untuk membuatnya aktif stdout?
Dennis Williamson

2
Ubah dieke printdan itu akan pergi ke stdout. Hanya dua karakter lagi.
Adam Bellaire

bekerja di ubuntu!
marinara

mengesankan perl hackistry
nandoP

Hasilnya dalam urutan terbalik :(
RSFalcon7

55

Ada alat yang sangat berguna yang saya gunakan yang disebut ncdu yang dirancang untuk menemukan folder dan file penggunaan disk yang sial, dan menghapusnya. Berbasis konsol, cepat dan ringan, dan memiliki paket pada semua distribusi utama.


Sangat bagus ... Saya ingin tahu apakah hasilnya dapat diumpankan ke standar ... Saya sangat malas sehingga saya tidak dapat membaca manual
ojblass

8
gt5 berada di nada yang sama; fitur pembunuhnya menampilkan pertumbuhan.
Tobu

1
Itu keren sekali! Dan jauh lebih cepat daripada bergaul dengan du, jika Anda hanya ingin mengidentifikasi direktori besar.
BurninLeo

44
du -k * | sort -nr | cut -f2 | xargs -d '\n' du -sh

Tidak dapat digunakan dengan du -k --total, memberikan kesalahan pada akhirnyadu: cannot access 'total': No such file or directory
laggingreflex

saya suka yang ini lagi jawaban lain. bagaimana Anda akan menampilkan hanya 50 hasil pertama?
Mau

1
@ Mauro - hanya pipa hasilnya headdengan menambahkan `| kepala -50` di akhir.
Samuel Lelièvre

21

Sejauh yang saya bisa lihat, Anda memiliki tiga opsi:

  1. Ubah duuntuk mengurutkan sebelum tampilan.
  2. Ubah sortuntuk mendukung ukuran manusia untuk jenis numerik.
  3. Poskan proses keluaran dari sortir untuk mengubah keluaran dasar menjadi dapat dibaca manusia.

Anda juga bisa melakukan du -kdan hidup dengan ukuran di KiB.

Untuk opsi 3 Anda dapat menggunakan skrip berikut:

#!/usr/bin/env python

import sys
import re

sizeRe = re.compile(r"^(\d+)(.*)$")

for line in sys.stdin.readlines():
    mo = sizeRe.match(line)
    if mo:
        size = int(mo.group(1))
        if size < 1024:
            size = str(size)+"K"
        elif size < 1024 ** 2:
            size = str(size/1024)+"M"
        else:
            size = str(size/(1024 ** 2))+"G"

        print "%s%s"%(size,mo.group(2))
    else:
        print line

20

Saya juga punya masalah itu dan saat ini saya sedang menggunakan solusi:

du -scBM | sort -n

Ini tidak akan menghasilkan nilai skala, tetapi selalu menghasilkan ukuran dalam megabyte. Itu kurang sempurna, tetapi bagi saya itu lebih baik daripada tidak sama sekali (atau menampilkan ukuran dalam byte).


Saya suka saklar th -BM, yang pada dasarnya sama dengan -m, tetapi ia memiliki keuntungan menampilkan ukuran dan M postfixed untuk itu, sehingga Anda mendapatkan 10M yang jauh lebih jelas daripada hanya 10 :)
Tom Feiner

Ini adalah solusi paling sederhana yang saya lihat sejauh ini di halaman ini, terima kasih!
Jeff Olson 515

19

Menemukan kiriman ini di tempat lain. Oleh karena itu, skrip shell ini akan melakukan apa yang Anda inginkan tanpa memanggil dusemuanya dua kali. Ini digunakan awkuntuk mengkonversi byte mentah ke format yang dapat dibaca manusia. Tentu saja, formatnya sedikit berbeda (semuanya dicetak ke satu tempat desimal presisi).

#/bin/bash
du -B1 | sort -nr  |awk '{sum=$1;
hum[1024**3]="G";hum[1024**2]="M";hum[1024]="K";
for (x=1024**3; x>=1024; x/=1024){
        if (sum>=x) { printf "%.1f%s\t\t",sum/x,hum[x];print $2;break
}}}'

Menjalankan ini di .vimdirektori saya menghasilkan:

4.4M            .
3.6M            ./colors
372.0K          ./plugin
128.0K          ./autoload
100.0K          ./syntax
100.0K          ./doc

(Saya harap skema warna 3,6M tidak berlebihan.)


1
Saya punya jawaban Perl juga, tapi saya pikir itu mungkin membuat orang membenci saya: du -B1 | sort -nr | perl -e '% h = (0 => b, 1 => K, 2 => M, 3 => G); untuk (<>) {($ s, @ f) = split / \ s + /; $ e = 3; $ e-- while (1024 ** $ e> $ s); $ v = ($ s / (1024 ** $ e)); printf "% -8s% s \ n", sprintf ($ v> = 100? "% d% s": "% .1f% s", $ s / (1024 ** $ e), $ h {$ e}), @ f;} '
Adam Bellaire

Meskipun jawaban Perl benar-benar memberikan formatnya lebih dekat ke du. Meskipun pembulatannya mati ... Sepertinya du selalu memberikan ceil () daripada round ()
Adam Bellaire

Hei, mengapa saya menggunakan hash di sana? Seharusnya sudah array ... pagi-otak menggerutu ....
Adam Bellaire

Menambahkan solusi Perl yang lebih baik sebagai jawaban lain.
Adam Bellaire

Kedua versi gagal ketika nama file mengandung spasi
Vi.

15

Versi ini digunakan awkuntuk membuat kolom tambahan untuk mengurutkan kunci. Itu hanya memanggil dusatu kali. Outputnya akan terlihat persis seperti du.

Saya telah membaginya menjadi beberapa baris, tetapi dapat dikombinasi ulang menjadi satu garis.

du -h |
  awk '{printf "%s %08.2f\t%s\n", 
    index("KMG", substr($1, length($1))),
    substr($1, 0, length($1)-1), $0}' |
  sort -r | cut -f2,3

Penjelasan:

  • BEGIN - buat string untuk mengindeks untuk menggantikan 1, 2, 3 untuk K, M, G untuk pengelompokan berdasarkan unit, jika tidak ada unit (ukurannya kurang dari 1K), maka tidak ada kecocokan dan nol dikembalikan (sempurna! )
  • cetak bidang baru - unit, nilai (untuk membuat alpha-sort berfungsi dengan baik, tanpa-empuk, panjang tetap) dan baris asli
  • indeks karakter terakhir dari bidang ukuran
  • tarik bagian numerik dari ukuran
  • urutkan hasilnya, buang kolom tambahan

Cobalah tanpa cutperintah untuk melihat apa yang dilakukannya.

Ini adalah versi yang melakukan pengurutan dalam skrip AWK dan tidak perlu cut:

du -h |
   awk '{idx = sprintf("%s %08.2f %s", 
         index("KMG", substr($1, length($1))),
         substr($1, 0, length($1)-1), $0);
         lines[idx] = $0}
    END {c = asorti(lines, sorted);
         for (i = c; i >= 1; i--)
           print lines[sorted[i]]}'

Terima kasih! ini adalah contoh pertama yang bekerja untuk saya di OS X 10.6 tidak termasuk perl / phython-scripts. dan terima kasih lagi untuk penjelasannya. selalu senang mempelajari sesuatu yang baru. awk tentu adalah alat yang ampuh.
Wolf

Terima kasih banyak untuk itu. Saya mengubah du untuk du -sh *menunjukkan hanya file dan direktori langsung tanpa keturunan rekursif.
HankCa

15

Berikut adalah contoh yang menunjukkan direktori dalam bentuk ringkas yang diringkas. Ini menangani spasi di direktori / nama file.

% du -s * | sort -rn | cut -f2- | xargs -d "\n" du -sh

53G  projects
21G  Desktop
7.2G VirtualBox VMs
3.7G db
3.3G SparkleShare
2.2G Dropbox
272M apps
47M  incoming
14M  bin
5.7M rpmbuild
68K  vimdir.tgz

1
pengguna macOS / OSX diperingatkan bahwa versi mac dari xargs tidak mendukung flag -d, dan jika Anda menghilangkannya, setiap direktori yang berisi spasi meminta setiap kata diuraikan secara terpisah yang tentu saja gagal.
jasonology

11

urutkan file berdasarkan ukuran dalam MB

du --block-size=MiB --max-depth=1 path | sort -n

9

Saya punya pembungkus python yang sederhana namun bermanfaat untuk du yang disebut dutop . Perhatikan bahwa kami (pengelola coreutils) sedang mempertimbangkan untuk menambahkan fungsionalitas untuk mengurutkan untuk mengurutkan output "manusia" secara langsung.


1
Memberi +1 untuk salah satu pengecualian langka dan valid untuk "melakukan satu hal dan melakukannya dengan benar". Kecuali seseorang mendapat semacam untuk memahami awalan SI dan / atau awalan biner.
Joachim Sauer

Dan seperti ptman menyebutkan di bawah ini: ta da ! ( sortbendera baru )
Tobu

9

Dapatkan satu lagi:

$ du -B1 | sort -nr | perl -MNumber::Bytes::Human=format_bytes -F'\t' -lane 'print format_bytes($F[0])."\t".$F[1]'

Saya mulai menyukai perl. Anda mungkin harus melakukan

$ cpan Number::Bytes::Human

pertama. Untuk semua peretas perl di luar sana: Ya, saya tahu bahwa bagian semacam itu juga dapat dilakukan di perl. Mungkin bagian du juga.


8

Cuplikan ini tanpa malu-malu tersangkut dari 'Jean-Pierre' dari http://www.unix.com/shell-programming-scripting/32555-du-h-sort.html . Apakah ada cara agar saya bisa lebih menghargai dia?

du -k | sort -nr | awk '
     BEGIN {
        split("KB,MB,GB,TB", Units, ",");
     }
     {
        u = 1;
        while ($1 >= 1024) {
           $1 = $1 / 1024;
           u += 1
        }
        $1 = sprintf("%.1f %s", $1, Units[u]);
        print $0;
     }
    '

saya pikir jika ini adalah angka yang sangat besar, maka unitnya hilang dan jumlah yang ditampilkan kecil ... coba23423423432423
nopole

7

Gunakan bendera "-g"

 -g, --general-numeric-sort
              compare according to general numerical value

Dan pada direktori / usr / local saya menghasilkan output seperti ini:

$ du |sort -g

0   ./lib/site_ruby/1.8/rubygems/digest
20  ./lib/site_ruby/1.8/rubygems/ext
20  ./share/xml
24  ./lib/perl
24  ./share/sgml
44  ./lib/site_ruby/1.8/rubygems/package
44  ./share/mime
52  ./share/icons/hicolor
56  ./share/icons
112 ./share/perl/5.10.0/YAML
132 ./lib/site_ruby/1.8/rubygems/commands
132 ./share/man/man3
136 ./share/man
156 ./share/perl/5.10.0
160 ./share/perl
488 ./share
560 ./lib/site_ruby/1.8/rubygems
604 ./lib/site_ruby/1.8
608 ./lib/site_ruby

4
Itu tidak memberikan hasil yang dapat dibaca manusia, yang merupakan apa yang dicari OP.

4

Yang lainnya:

du -h | perl -e'
@l{ K, M, G } = ( 1 .. 3 );
print sort {
    ($aa) = $a =~ /(\w)\s+/;
    ($bb) = $b =~ /(\w)\s+/;
    $l{$aa} <=> $l{$bb} || $a <=> $b
  } <>'

4

Berikut adalah metode sederhana yang saya gunakan, penggunaan sumber daya sangat rendah dan memberi Anda apa yang Anda butuhkan:

du --max-depth=1 | sort -n | awk 'BEGIN {OFMT = "%.0f"} {print $1/1024,"MB", $2}'

0 MB ./etc
1 MB ./mail
2 MB ./tmp
123 MB ./public_html

4

Menemukan ini online ... tampaknya berfungsi OK

du -sh * | tee /tmp/duout.txt | grep G | sort -rn ; cat /tmp/duout.txt | grep M | sort -rn ; cat /tmp/duout.txt | grep K | sort -rn ; rm /tmp/duout.txt

Longgar berdasarkan one-liner ini, saya membuat skrip untuk memberikan keluaran (1) yang dapat dibaca oleh manusia dan diurutkan. Silakan merujuk jawaban saya, serverfault.com/a/937459/218692 .
Tripp Kinetics

3

Saya belajar awk dari meramu contoh ini kemarin. Butuh waktu, tetapi itu sangat menyenangkan, dan saya belajar cara menggunakan awk.

Ini hanya berjalan du sekali, dan memiliki output yang mirip dengan du -h

du --max-depth=0 -k * | sort -nr | awk '{ if($1>=1024*1024) {size=$1/1024/1024; unit="G"} else if($1>=1024) {size=$1/1024; unit="M"} else {size=$1; unit="K"}; if(size<10) format="%.1f%s"; else format="%.0f%s"; res=sprintf(format,size,unit); printf "%-8s %s\n",res,$2 }'

Ini menunjukkan angka di bawah 10 dengan satu titik desimal.


3

du -cka --max-depth = 1 / var / log | sort -rn | kepala -10 | awk '{print ($ 1) / 1024, "MB", $ 2'}


2

Jika Anda perlu menangani spasi, Anda dapat menggunakan yang berikut ini

 du -d 1| sort -nr | cut -f2 | sed 's/ /\\ /g' | xargs du -sh

Pernyataan sed tambahan akan membantu meringankan masalah dengan folder dengan nama seperti Dukungan Aplikasi


Baru saja mencoba ini di macOS Sierra. Bekerja seperti yang diharapkan. Bagus!
jasonology

1

Voa:

du -sk /var/log/* | sort -rn | awk '{print $2}' | xargs -ia du -hs "a"

1

http://dev.yorhel.nl/ncdu

perintah: ncdu

Navigasi direktori, pengurutan (nama dan ukuran), grafik, dapat dibaca manusia, dll ...


1
Utilitas hebat, tetapi tidak diinstal secara default pada OS apa pun yang saya ketahui. Tidak perlu masalah, tetapi satu program lagi yang harus
dijaga

1

awkSolusi lain -

du -k ./* | sort -nr | 
awk '
{split("KB,MB,GB",size,",");}
{x = 1;while ($1 >= 1024) 
{$1 = $1 / 1024;x = x + 1} $1 = sprintf("%-4.2f%s", $1, size[x]); print $0;}'


[jaypal~/Desktop/Reference]$ du -k ./* | sort -nr | awk '{split("KB,MB,GB",size,",");}{x = 1;while ($1 >= 1024) {$1 = $1 / 1024;x = x + 1} $1 = sprintf("%-4.2f%s", $1, size[x]); print $0;}'
15.92MB ./Personal
13.82MB ./Personal/Docs
2.35MB ./Work Docs
1.59MB ./Work Docs/Work
1.46MB ./Personal/Raa
584.00KB ./scan 1.pdf
544.00KB ./Personal/Resume
44.00KB ./Membership.xlsx
16.00KB ./Membership Transmittal Template.xlsx

1

Saya telah menggunakan solusi yang disediakan oleh @ptman, tetapi perubahan server baru-baru ini membuatnya tidak lagi layak. Sebagai gantinya, saya menggunakan skrip bash berikut:

#!/bin/bash
# File: duf.sh
# list contents of the current directory by increasing 
#+size in human readable format

# for some, "-d 1" will be "--maxdepth=1"
du -k -d 1 | sort -g | awk '
{
if($1<1024)
    printf("%.0f KB\t%s",$1,$2);
else if($1<1024*1024)
    printf("%.1f MB\t%s",$1/1024,$2);
else
    printf("%.1f GB\t%s",$1/1024/1024,$2);
}'

du -d 1Sintaks BSD telah didukung oleh GNU du sejak coreutils 8.6 dirilis pada 2010 (meskipun ketersediaan Red Hat pertama adalah RHEL 7 pada 2014), jadi Anda tidak lagi membutuhkannya --maxdepth=1. Saya sendiri baru tahu tentang ini.
Adam Katz


1

Ada banyak jawaban di sini, banyak di antaranya adalah duplikat. Saya melihat tiga tren: menyalurkan melalui panggilan kedua, menggunakan kode shell / awk yang rumit, dan menggunakan bahasa lain.

Berikut ini adalah solusi yang sesuai dengan POSIX menggunakan du dan awk yang seharusnya bekerja pada setiap sistem.

Saya telah mengambil pendekatan yang sedikit berbeda, menambahkan -xuntuk memastikan kita tetap pada sistem file yang sama (saya hanya perlu operasi ini ketika saya kekurangan ruang disk, jadi mengapa menyingkirkan hal-hal yang telah saya pasang di pohon FS ini atau pindah dan symlinked back?) dan menampilkan unit konstan untuk mempermudah penguraian visual. Dalam hal ini, saya biasanya memilih untuk tidak menyortir sehingga saya dapat melihat struktur hierarkis dengan lebih baik.

sudo du -x | awk '
  $1 > 2^20 { s=$1; $1=""; printf "%7sG%s\n", sprintf("%.2f",s/2^21), $0 }'

(Karena ini dalam unit yang konsisten, Anda dapat menambahkan | sort -njika Anda benar-benar ingin mengurutkan hasil.)

Ini menyaring direktori mana pun yang kontennya (kumulatif) gagal melebihi 512MB dan kemudian menampilkan ukuran dalam gigabytes. Secara default, du menggunakan ukuran blok 512-byte (sehingga kondisi awk ini dari 2 20 blok adalah 512MB dan yang 2 21 pembagi mengkonversi unit untuk GB - kita bisa menggunakan du -kxdengan $1 > 512*1024dan s/1024^2untuk lebih terbaca-manusia). Di dalam kondisi awk, kami mengatur ske ukuran sehingga kami dapat menghapusnya dari baris ( $0). Ini mempertahankan pembatas (yang diciutkan ke satu ruang tunggal), sehingga final %smewakili ruang dan kemudian nama direktori gabungan. %7smenyelaraskan %.2fukuran GB bulat (meningkat menjadi %8sjika Anda memiliki> 10TB).

Tidak seperti kebanyakan solusi di sini, ini benar-benar mendukung direktori dengan spasi di namanya (meskipun setiap solusi, termasuk yang ini, akan salah menangani nama direktori yang berisi jeda baris).


0

Setidaknya dengan alat yang biasa, ini akan sulit karena format angka yang dapat dibaca manusia berada di (perhatikan bahwa semacam melakukan "pekerjaan yang baik" di sini karena mengurutkan angka - 508, 64, 61, 2, 2 - itu tidak bisa mengurutkan angka floating point dengan pengganda tambahan).

Saya akan mencobanya sebaliknya - gunakan output dari "du | sort -n -r" dan kemudian mengonversi angka ke format yang dapat dibaca manusia dengan beberapa skrip atau program.


0

Yang bisa Anda coba adalah:

for i in `du -s * | sort -n | cut -f2`
do
  du -h $i;
done

Semoga itu bisa membantu.


itulah yang dilakukan xargs ;-)
cadrian

hehe, saya selalu lupa tentang xargs. ;) Pada akhirnya, apa pun yang membuat pekerjaan selesai.

MacOSX secara default (yaitu di luar home-brew) tidak mendukung yang tepat xargssehingga formulir ini diperlukan. Namun untuk file dengan spasi di dalamnya, Anda perlu mengatur IFS:IFS=$'\n'
HankCa

0
du | sort -nr | awk '{ cmd = "du -h -d0 "$2"| cut -f1"; cmd | getline human; close(cmd); print human"\t"$2 }'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.