mirror of
https://github.com/bootandy/dust.git
synced 2026-06-08 11:29:05 +03:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 15845dee3e | |||
| 57115bd624 | |||
| 0ac818a2f5 | |||
| a91aa62060 | |||
| a7b82f32d7 | |||
| 72b811c278 | |||
| b478534b22 | |||
| 2ca7177446 | |||
| e858f9e976 | |||
| 0a67191054 | |||
| c363e5ff8b | |||
| c148cd9044 | |||
| 2893f73f47 | |||
| 5103ebe0d8 |
@@ -81,13 +81,41 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
# { os, target, cargo-options, features, use-cross, toolchain }
|
# { os, target, cargo-options, features, use-cross, toolchain }
|
||||||
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , use-cross: use-cross }
|
- {
|
||||||
- { os: ubuntu-latest , target: aarch64-unknown-linux-musl , use-cross: use-cross }
|
os: ubuntu-latest,
|
||||||
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , use-cross: use-cross }
|
target: aarch64-unknown-linux-gnu,
|
||||||
- { os: ubuntu-latest , target: i686-unknown-linux-gnu , use-cross: use-cross }
|
use-cross: use-cross,
|
||||||
- { os: ubuntu-latest , target: i686-unknown-linux-musl , use-cross: use-cross }
|
}
|
||||||
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , use-cross: use-cross }
|
- {
|
||||||
- { os: ubuntu-latest , target: x86_64-unknown-linux-musl , use-cross: use-cross }
|
os: ubuntu-latest,
|
||||||
|
target: aarch64-unknown-linux-musl,
|
||||||
|
use-cross: use-cross,
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
os: ubuntu-latest,
|
||||||
|
target: arm-unknown-linux-gnueabihf,
|
||||||
|
use-cross: use-cross,
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
os: ubuntu-latest,
|
||||||
|
target: i686-unknown-linux-gnu,
|
||||||
|
use-cross: use-cross,
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
os: ubuntu-latest,
|
||||||
|
target: i686-unknown-linux-musl,
|
||||||
|
use-cross: use-cross,
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
os: ubuntu-latest,
|
||||||
|
target: x86_64-unknown-linux-gnu,
|
||||||
|
use-cross: use-cross,
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
os: ubuntu-latest,
|
||||||
|
target: x86_64-unknown-linux-musl,
|
||||||
|
use-cross: use-cross,
|
||||||
|
}
|
||||||
- { os: macos-latest, target: x86_64-apple-darwin }
|
- { os: macos-latest, target: x86_64-apple-darwin }
|
||||||
- { os: windows-latest, target: i686-pc-windows-gnu }
|
- { os: windows-latest, target: i686-pc-windows-gnu }
|
||||||
- { os: windows-latest, target: i686-pc-windows-msvc }
|
- { os: windows-latest, target: i686-pc-windows-msvc }
|
||||||
|
|||||||
Generated
+33
-1
@@ -118,6 +118,12 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
@@ -197,10 +203,11 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "du-dust"
|
name = "du-dust"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
|
"atty",
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"config-file",
|
"config-file",
|
||||||
@@ -210,6 +217,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"stfu8",
|
"stfu8",
|
||||||
|
"sysinfo",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"terminal_size",
|
"terminal_size",
|
||||||
"thousands",
|
"thousands",
|
||||||
@@ -322,6 +330,15 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.13.1"
|
version = "1.13.1"
|
||||||
@@ -518,6 +535,21 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.26.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c375d5fd899e32847b8566e10598d6e9f1d9b55ec6de3cdf9e7da4bdc51371bc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"ntapi",
|
||||||
|
"once_cell",
|
||||||
|
"rayon",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "du-dust"
|
name = "du-dust"
|
||||||
description = "A more intuitive version of du"
|
description = "A more intuitive version of du"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
|
authors = ["bootandy <bootandy@gmail.com>", "nebkor <code@ardent.nebcorp.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@@ -28,6 +28,7 @@ strip = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
|
atty = "0.2.14"
|
||||||
clap = "3.2.17"
|
clap = "3.2.17"
|
||||||
lscolors = "0.7"
|
lscolors = "0.7"
|
||||||
terminal_size = "0.1"
|
terminal_size = "0.1"
|
||||||
@@ -39,6 +40,7 @@ regex = "1"
|
|||||||
config-file = "0.2"
|
config-file = "0.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
directories = "4"
|
directories = "4"
|
||||||
|
sysinfo = "0.26"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi-util = "0.1"
|
winapi-util = "0.1"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
[](https://travis-ci.org/bootandy/dust)
|
[](https://travis-ci.org/bootandy/dust)
|
||||||
|
|
||||||
# Dust
|
# Dust
|
||||||
@@ -10,35 +9,41 @@ du + rust = dust. Like du but more intuitive.
|
|||||||
Because I want an easy way to see where my disk is being used.
|
Because I want an easy way to see where my disk is being used.
|
||||||
|
|
||||||
# Demo
|
# Demo
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
#### Cargo <a href="https://repology.org/project/du-dust/versions"><img src="https://repology.org/badge/vertical-allrepos/du-dust.svg" alt="Packaging status" align="right"></a>
|
#### Cargo <a href="https://repology.org/project/du-dust/versions"><img src="https://repology.org/badge/vertical-allrepos/du-dust.svg" alt="Packaging status" align="right"></a>
|
||||||
|
|
||||||
* `cargo install du-dust`
|
- `cargo install du-dust`
|
||||||
|
|
||||||
#### 🍺 Homebrew (Mac OS)
|
#### 🍺 Homebrew (Mac OS)
|
||||||
|
|
||||||
* `brew install dust`
|
- `brew install dust`
|
||||||
|
|
||||||
#### 🍺 Homebrew (Linux)
|
#### 🍺 Homebrew (Linux)
|
||||||
|
|
||||||
* `brew tap tgotwig/linux-dust && brew install dust`
|
- `brew tap tgotwig/linux-dust && brew install dust`
|
||||||
|
|
||||||
#### [Pacstall](https://github.com/pacstall/pacstall) (Debian/Ubuntu)
|
#### [Pacstall](https://github.com/pacstall/pacstall) (Debian/Ubuntu)
|
||||||
|
|
||||||
* `pacstall -I dust-bin`
|
- `pacstall -I dust-bin`
|
||||||
|
|
||||||
|
#### [deb-get](https://github.com/wimpysworld/deb-get) (Debian/Ubuntu)
|
||||||
|
|
||||||
|
- `deb-get install du-dust`
|
||||||
|
|
||||||
#### Windows:
|
#### Windows:
|
||||||
* Windows GNU version - works
|
|
||||||
* Windows MSVC - requires: [VCRUNTIME140.dll](https://docs.microsoft.com/en-gb/cpp/windows/latest-supported-vc-redist?view=msvc-170)
|
- Windows GNU version - works
|
||||||
|
- Windows MSVC - requires: [VCRUNTIME140.dll](https://docs.microsoft.com/en-gb/cpp/windows/latest-supported-vc-redist?view=msvc-170)
|
||||||
|
|
||||||
#### Download
|
#### Download
|
||||||
|
|
||||||
* Download Linux/Mac binary from [Releases](https://github.com/bootandy/dust/releases)
|
- Download Linux/Mac binary from [Releases](https://github.com/bootandy/dust/releases)
|
||||||
* unzip file: `tar -xvf _downloaded_file.tar.gz`
|
- unzip file: `tar -xvf _downloaded_file.tar.gz`
|
||||||
* move file to executable path: `sudo mv dust /usr/local/bin/`
|
- move file to executable path: `sudo mv dust /usr/local/bin/`
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -58,6 +63,7 @@ Usage: dust -p (full-path - Show fullpath of the subdirectories)
|
|||||||
Usage: dust -s (apparent-size - shows the length of the file as opposed to the amount of disk space it uses)
|
Usage: dust -s (apparent-size - shows the length of the file as opposed to the amount of disk space it uses)
|
||||||
Usage: dust -n 30 (Shows 30 directories instead of the default [default is terminal height])
|
Usage: dust -n 30 (Shows 30 directories instead of the default [default is terminal height])
|
||||||
Usage: dust -d 3 (Shows 3 levels of subdirectories)
|
Usage: dust -d 3 (Shows 3 levels of subdirectories)
|
||||||
|
Usage: dust -D (Show only directories (eg dust -D))
|
||||||
Usage: dust -r (reverse order of output)
|
Usage: dust -r (reverse order of output)
|
||||||
Usage: dust -H (si print sizes in powers of 1000 instead of 1024)
|
Usage: dust -H (si print sizes in powers of 1000 instead of 1024)
|
||||||
Usage: dust -X ignore (ignore all files and directories with the name 'ignore')
|
Usage: dust -X ignore (ignore all files and directories with the name 'ignore')
|
||||||
@@ -69,18 +75,17 @@ Usage: dust -f (Count files instead of diskspace)
|
|||||||
Usage: dust -t (Group by filetype)
|
Usage: dust -t (Group by filetype)
|
||||||
Usage: dust -z 10M (min-size, Only include files larger than 10M)
|
Usage: dust -z 10M (min-size, Only include files larger than 10M)
|
||||||
Usage: dust -e regex (Only include files matching this regex (eg dust -e "\.png$" would match png files))
|
Usage: dust -e regex (Only include files matching this regex (eg dust -e "\.png$" would match png files))
|
||||||
Usage: dust -v regex (Exculde files matching this regex (eg dust -v "\.png$" would ignore png files))
|
Usage: dust -v regex (Exclude files matching this regex (eg dust -v "\.png$" would ignore png files))
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Alternatives
|
## Alternatives
|
||||||
|
|
||||||
* [NCDU](https://dev.yorhel.nl/ncdu)
|
- [NCDU](https://dev.yorhel.nl/ncdu)
|
||||||
* [dutree](https://github.com/nachoparker/dutree)
|
- [dutree](https://github.com/nachoparker/dutree)
|
||||||
* [dua](https://github.com/Byron/dua-cli/)
|
- [dua](https://github.com/Byron/dua-cli/)
|
||||||
* [pdu](https://github.com/KSXGitHub/parallel-disk-usage)
|
- [pdu](https://github.com/KSXGitHub/parallel-disk-usage)
|
||||||
* [dirstat-rs](https://github.com/scullionw/dirstat-rs)
|
- [dirstat-rs](https://github.com/scullionw/dirstat-rs)
|
||||||
* du -d 1 -h | sort -h
|
- du -d 1 -h | sort -h
|
||||||
|
|
||||||
Note: Apparent-size is calculated slightly differently in dust to gdu. In dust each hard link is counted as using file_length space. In gdu only the first entry is counted.
|
Note: Apparent-size is calculated slightly differently in dust to gdu. In dust each hard link is counted as using file_length space. In gdu only the first entry is counted.
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ _dust() {
|
|||||||
'--version[Print version information]' \
|
'--version[Print version information]' \
|
||||||
'-p[Subdirectories will not have their path shortened]' \
|
'-p[Subdirectories will not have their path shortened]' \
|
||||||
'--full-paths[Subdirectories will not have their path shortened]' \
|
'--full-paths[Subdirectories will not have their path shortened]' \
|
||||||
|
'(-L --dereference-links)-l[Ignore links]' \
|
||||||
|
'(-L --dereference-links)--ignore-links[Ignore links]' \
|
||||||
|
'(-l --ignore-links)-L[dereference sym links - Treat sym links as directories and go into them]' \
|
||||||
|
'(-l --ignore-links)--dereference-links[dereference sym links - Treat sym links as directories and go into them]' \
|
||||||
'-x[Only count the files and directories on the same filesystem as the supplied directory]' \
|
'-x[Only count the files and directories on the same filesystem as the supplied directory]' \
|
||||||
'--limit-filesystem[Only count the files and directories on the same filesystem as the supplied directory]' \
|
'--limit-filesystem[Only count the files and directories on the same filesystem as the supplied directory]' \
|
||||||
'-s[Use file length instead of blocks]' \
|
'-s[Use file length instead of blocks]' \
|
||||||
@@ -54,6 +58,8 @@ _dust() {
|
|||||||
'(-d --depth)--file_types[show only these file types]' \
|
'(-d --depth)--file_types[show only these file types]' \
|
||||||
'-H[print sizes in powers of 1000 (e.g., 1.1G)]' \
|
'-H[print sizes in powers of 1000 (e.g., 1.1G)]' \
|
||||||
'--si[print sizes in powers of 1000 (e.g., 1.1G)]' \
|
'--si[print sizes in powers of 1000 (e.g., 1.1G)]' \
|
||||||
|
'-D[Only directories will be displayed.]' \
|
||||||
|
'--only-dir[Only directories will be displayed.]' \
|
||||||
'*::inputs:' \
|
'*::inputs:' \
|
||||||
&& ret=0
|
&& ret=0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock {
|
|||||||
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information')
|
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information')
|
||||||
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
[CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
||||||
[CompletionResult]::new('--full-paths', 'full-paths', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
[CompletionResult]::new('--full-paths', 'full-paths', [CompletionResultType]::ParameterName, 'Subdirectories will not have their path shortened')
|
||||||
|
[CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'Ignore links')
|
||||||
|
[CompletionResult]::new('--ignore-links', 'ignore-links', [CompletionResultType]::ParameterName, 'Ignore links')
|
||||||
|
[CompletionResult]::new('-L', 'L', [CompletionResultType]::ParameterName, 'dereference sym links - Treat sym links as directories and go into them')
|
||||||
|
[CompletionResult]::new('--dereference-links', 'dereference-links', [CompletionResultType]::ParameterName, 'dereference sym links - Treat sym links as directories and go into them')
|
||||||
[CompletionResult]::new('-x', 'x', [CompletionResultType]::ParameterName, 'Only count the files and directories on the same filesystem as the supplied directory')
|
[CompletionResult]::new('-x', 'x', [CompletionResultType]::ParameterName, 'Only count the files and directories on the same filesystem as the supplied directory')
|
||||||
[CompletionResult]::new('--limit-filesystem', 'limit-filesystem', [CompletionResultType]::ParameterName, 'Only count the files and directories on the same filesystem as the supplied directory')
|
[CompletionResult]::new('--limit-filesystem', 'limit-filesystem', [CompletionResultType]::ParameterName, 'Only count the files and directories on the same filesystem as the supplied directory')
|
||||||
[CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Use file length instead of blocks')
|
[CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Use file length instead of blocks')
|
||||||
@@ -60,6 +64,8 @@ Register-ArgumentCompleter -Native -CommandName 'dust' -ScriptBlock {
|
|||||||
[CompletionResult]::new('--file_types', 'file_types', [CompletionResultType]::ParameterName, 'show only these file types')
|
[CompletionResult]::new('--file_types', 'file_types', [CompletionResultType]::ParameterName, 'show only these file types')
|
||||||
[CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'print sizes in powers of 1000 (e.g., 1.1G)')
|
[CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'print sizes in powers of 1000 (e.g., 1.1G)')
|
||||||
[CompletionResult]::new('--si', 'si', [CompletionResultType]::ParameterName, 'print sizes in powers of 1000 (e.g., 1.1G)')
|
[CompletionResult]::new('--si', 'si', [CompletionResultType]::ParameterName, 'print sizes in powers of 1000 (e.g., 1.1G)')
|
||||||
|
[CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'Only directories will be displayed.')
|
||||||
|
[CompletionResult]::new('--only-dir', 'only-dir', [CompletionResultType]::ParameterName, 'Only directories will be displayed.')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ _dust() {
|
|||||||
|
|
||||||
case "${cmd}" in
|
case "${cmd}" in
|
||||||
dust)
|
dust)
|
||||||
opts="-h -V -d -n -p -X -x -s -r -c -b -z -f -i -v -e -t -w -H --help --version --depth --number-of-lines --full-paths --ignore-directory --limit-filesystem --apparent-size --reverse --no-colors --no-percent-bars --min-size --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --si <inputs>..."
|
opts="-h -V -d -n -p -X -l -L -x -s -r -c -b -z -f -i -v -e -t -w -H -D --help --version --depth --number-of-lines --full-paths --ignore-directory --ignore-links --dereference-links --limit-filesystem --apparent-size --reverse --no-colors --no-percent-bars --min-size --skip-total --filecount --ignore_hidden --invert-filter --filter --file_types --terminal_width --si --only-dir <inputs>..."
|
||||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ set edit:completion:arg-completer[dust] = {|@words|
|
|||||||
cand --version 'Print version information'
|
cand --version 'Print version information'
|
||||||
cand -p 'Subdirectories will not have their path shortened'
|
cand -p 'Subdirectories will not have their path shortened'
|
||||||
cand --full-paths 'Subdirectories will not have their path shortened'
|
cand --full-paths 'Subdirectories will not have their path shortened'
|
||||||
|
cand -l 'Ignore links'
|
||||||
|
cand --ignore-links 'Ignore links'
|
||||||
|
cand -L 'dereference sym links - Treat sym links as directories and go into them'
|
||||||
|
cand --dereference-links 'dereference sym links - Treat sym links as directories and go into them'
|
||||||
cand -x 'Only count the files and directories on the same filesystem as the supplied directory'
|
cand -x 'Only count the files and directories on the same filesystem as the supplied directory'
|
||||||
cand --limit-filesystem 'Only count the files and directories on the same filesystem as the supplied directory'
|
cand --limit-filesystem 'Only count the files and directories on the same filesystem as the supplied directory'
|
||||||
cand -s 'Use file length instead of blocks'
|
cand -s 'Use file length instead of blocks'
|
||||||
@@ -57,6 +61,8 @@ set edit:completion:arg-completer[dust] = {|@words|
|
|||||||
cand --file_types 'show only these file types'
|
cand --file_types 'show only these file types'
|
||||||
cand -H 'print sizes in powers of 1000 (e.g., 1.1G)'
|
cand -H 'print sizes in powers of 1000 (e.g., 1.1G)'
|
||||||
cand --si 'print sizes in powers of 1000 (e.g., 1.1G)'
|
cand --si 'print sizes in powers of 1000 (e.g., 1.1G)'
|
||||||
|
cand -D 'Only directories will be displayed.'
|
||||||
|
cand --only-dir 'Only directories will be displayed.'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
$completions[$command]
|
$completions[$command]
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ complete -c dust -s w -l terminal_width -d 'Specify width of output overriding t
|
|||||||
complete -c dust -s h -l help -d 'Print help information'
|
complete -c dust -s h -l help -d 'Print help information'
|
||||||
complete -c dust -s V -l version -d 'Print version information'
|
complete -c dust -s V -l version -d 'Print version information'
|
||||||
complete -c dust -s p -l full-paths -d 'Subdirectories will not have their path shortened'
|
complete -c dust -s p -l full-paths -d 'Subdirectories will not have their path shortened'
|
||||||
|
complete -c dust -s l -l ignore-links -d 'Ignore links'
|
||||||
|
complete -c dust -s L -l dereference-links -d 'dereference sym links - Treat sym links as directories and go into them'
|
||||||
complete -c dust -s x -l limit-filesystem -d 'Only count the files and directories on the same filesystem as the supplied directory'
|
complete -c dust -s x -l limit-filesystem -d 'Only count the files and directories on the same filesystem as the supplied directory'
|
||||||
complete -c dust -s s -l apparent-size -d 'Use file length instead of blocks'
|
complete -c dust -s s -l apparent-size -d 'Use file length instead of blocks'
|
||||||
complete -c dust -s r -l reverse -d 'Print tree upside down (biggest highest)'
|
complete -c dust -s r -l reverse -d 'Print tree upside down (biggest highest)'
|
||||||
@@ -18,3 +20,4 @@ complete -c dust -s f -l filecount -d 'Directory \'size\' is number of child fil
|
|||||||
complete -c dust -s i -l ignore_hidden -d 'Do not display hidden files'
|
complete -c dust -s i -l ignore_hidden -d 'Do not display hidden files'
|
||||||
complete -c dust -s t -l file_types -d 'show only these file types'
|
complete -c dust -s t -l file_types -d 'show only these file types'
|
||||||
complete -c dust -s H -l si -d 'print sizes in powers of 1000 (e.g., 1.1G)'
|
complete -c dust -s H -l si -d 'print sizes in powers of 1000 (e.g., 1.1G)'
|
||||||
|
complete -c dust -s D -l only-dir -d 'Only directories will be displayed.'
|
||||||
|
|||||||
+21
-1
@@ -34,6 +34,20 @@ pub fn build_cli() -> Command<'static> {
|
|||||||
.multiple_occurrences(true)
|
.multiple_occurrences(true)
|
||||||
.help("Exclude any file or directory with this name"),
|
.help("Exclude any file or directory with this name"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("ignore_links")
|
||||||
|
.short('l')
|
||||||
|
.long("ignore-links")
|
||||||
|
.conflicts_with("dereference_links")
|
||||||
|
.help("Ignore links"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("dereference_links")
|
||||||
|
.short('L')
|
||||||
|
.long("dereference-links")
|
||||||
|
.conflicts_with("ignore_links")
|
||||||
|
.help("dereference sym links - Treat sym links as directories and go into them"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("limit_filesystem")
|
Arg::new("limit_filesystem")
|
||||||
.short('x')
|
.short('x')
|
||||||
@@ -131,5 +145,11 @@ pub fn build_cli() -> Command<'static> {
|
|||||||
.long("si")
|
.long("si")
|
||||||
.help("print sizes in powers of 1000 (e.g., 1.1G)")
|
.help("print sizes in powers of 1000 (e.g., 1.1G)")
|
||||||
)
|
)
|
||||||
.arg(Arg::new("inputs").multiple_occurrences(true).default_value("."))
|
.arg(Arg::new("inputs").multiple_occurrences(true))
|
||||||
|
.arg(
|
||||||
|
Arg::new("only_dir")
|
||||||
|
.short('D')
|
||||||
|
.long("only-dir")
|
||||||
|
.help("Only directories will be displayed."),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub struct Config {
|
|||||||
pub ignore_hidden: Option<bool>,
|
pub ignore_hidden: Option<bool>,
|
||||||
pub iso: Option<bool>,
|
pub iso: Option<bool>,
|
||||||
pub min_size: Option<String>,
|
pub min_size: Option<String>,
|
||||||
|
pub only_dir: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@@ -61,6 +62,9 @@ impl Config {
|
|||||||
size_from_param
|
size_from_param
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn get_only_dir(&self, options: &ArgMatches) -> bool {
|
||||||
|
Some(true) == self.only_dir || options.is_present("only_dir")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_min_size(input: &str, iso: bool) -> Option<usize> {
|
fn convert_min_size(input: &str, iso: bool) -> Option<usize> {
|
||||||
|
|||||||
+13
-8
@@ -26,6 +26,8 @@ pub struct WalkData<'a> {
|
|||||||
pub use_apparent_size: bool,
|
pub use_apparent_size: bool,
|
||||||
pub by_filecount: bool,
|
pub by_filecount: bool,
|
||||||
pub ignore_hidden: bool,
|
pub ignore_hidden: bool,
|
||||||
|
pub ignore_links: bool,
|
||||||
|
pub follow_links: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: WalkData) -> (Vec<Node>, bool) {
|
pub fn walk_it(dirs: HashSet<PathBuf>, walk_data: WalkData) -> (Vec<Node>, bool) {
|
||||||
@@ -141,12 +143,17 @@ fn walk(
|
|||||||
|
|
||||||
// return walk(entry.path(), permissions_flag, ignore_directories, allowed_filesystems, use_apparent_size, by_filecount, ignore_hidden);
|
// return walk(entry.path(), permissions_flag, ignore_directories, allowed_filesystems, use_apparent_size, by_filecount, ignore_hidden);
|
||||||
|
|
||||||
if !ignore_file(entry, walk_data) {
|
if ignore_file(entry, walk_data) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
if let Ok(data) = entry.file_type() {
|
if let Ok(data) = entry.file_type() {
|
||||||
return if data.is_dir() && !data.is_symlink() {
|
if data.is_symlink() && walk_data.ignore_links {
|
||||||
walk(entry.path(), permissions_flag, walk_data, depth + 1)
|
return None;
|
||||||
} else {
|
}
|
||||||
build_node(
|
if data.is_dir() || (walk_data.follow_links && data.is_symlink()) {
|
||||||
|
return walk(entry.path(), permissions_flag, walk_data, depth + 1);
|
||||||
|
}
|
||||||
|
return build_node(
|
||||||
entry.path(),
|
entry.path(),
|
||||||
vec![],
|
vec![],
|
||||||
walk_data.filter_regex,
|
walk_data.filter_regex,
|
||||||
@@ -156,9 +163,7 @@ fn walk(
|
|||||||
data.is_file(),
|
data.is_file(),
|
||||||
walk_data.by_filecount,
|
walk_data.by_filecount,
|
||||||
depth,
|
depth,
|
||||||
)
|
);
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
permissions_flag.store(true, atomic::Ordering::Relaxed);
|
permissions_flag.store(true, atomic::Ordering::Relaxed);
|
||||||
|
|||||||
+3
-3
@@ -88,7 +88,7 @@ impl DrawData<'_> {
|
|||||||
let mut num_not_my_bar = (chars_in_bar as i32) - num_bars as i32;
|
let mut num_not_my_bar = (chars_in_bar as i32) - num_bars as i32;
|
||||||
|
|
||||||
let mut new_bar = "".to_string();
|
let mut new_bar = "".to_string();
|
||||||
let idx = 5 - min(4, max(1, level));
|
let idx = 5 - level.clamp(1, 4);
|
||||||
|
|
||||||
for c in self.percent_bar.chars() {
|
for c in self.percent_bar.chars() {
|
||||||
num_not_my_bar -= 1;
|
num_not_my_bar -= 1;
|
||||||
@@ -141,10 +141,10 @@ pub fn draw_it(
|
|||||||
let longest_string_length =
|
let longest_string_length =
|
||||||
find_longest_dir_name(root_node, num_indent_chars, allowed_width, !use_full_path);
|
find_longest_dir_name(root_node, num_indent_chars, allowed_width, !use_full_path);
|
||||||
|
|
||||||
let max_bar_length = if no_percent_bars || longest_string_length + 7 >= allowed_width as usize {
|
let max_bar_length = if no_percent_bars || longest_string_length + 7 >= allowed_width {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
allowed_width as usize - longest_string_length - 7
|
allowed_width - longest_string_length - 7
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_size_bar = repeat(BLOCKS[0]).take(max_bar_length).collect();
|
let first_size_bar = repeat(BLOCKS[0]).take(max_bar_length).collect();
|
||||||
|
|||||||
+12
-4
@@ -8,6 +8,7 @@ use std::path::PathBuf;
|
|||||||
pub fn get_biggest(
|
pub fn get_biggest(
|
||||||
top_level_nodes: Vec<Node>,
|
top_level_nodes: Vec<Node>,
|
||||||
min_size: Option<usize>,
|
min_size: Option<usize>,
|
||||||
|
only_dir: bool,
|
||||||
n: usize,
|
n: usize,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
using_a_filter: bool,
|
using_a_filter: bool,
|
||||||
@@ -23,14 +24,14 @@ pub fn get_biggest(
|
|||||||
let mut allowed_nodes = HashSet::new();
|
let mut allowed_nodes = HashSet::new();
|
||||||
|
|
||||||
allowed_nodes.insert(root.name.as_path());
|
allowed_nodes.insert(root.name.as_path());
|
||||||
heap = add_children(using_a_filter, min_size, &root, depth, heap);
|
heap = add_children(using_a_filter, min_size, only_dir, &root, depth, heap);
|
||||||
|
|
||||||
for _ in number_top_level_nodes..n {
|
for _ in number_top_level_nodes..n {
|
||||||
let line = heap.pop();
|
let line = heap.pop();
|
||||||
match line {
|
match line {
|
||||||
Some(line) => {
|
Some(line) => {
|
||||||
allowed_nodes.insert(line.name.as_path());
|
allowed_nodes.insert(line.name.as_path());
|
||||||
heap = add_children(using_a_filter, min_size, line, depth, heap);
|
heap = add_children(using_a_filter, min_size, only_dir, line, depth, heap);
|
||||||
}
|
}
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
@@ -41,15 +42,22 @@ pub fn get_biggest(
|
|||||||
fn add_children<'a>(
|
fn add_children<'a>(
|
||||||
using_a_filter: bool,
|
using_a_filter: bool,
|
||||||
min_size: Option<usize>,
|
min_size: Option<usize>,
|
||||||
|
only_dir: bool,
|
||||||
file_or_folder: &'a Node,
|
file_or_folder: &'a Node,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
mut heap: BinaryHeap<&'a Node>,
|
mut heap: BinaryHeap<&'a Node>,
|
||||||
) -> BinaryHeap<&'a Node> {
|
) -> BinaryHeap<&'a Node> {
|
||||||
if depth > file_or_folder.depth {
|
if depth > file_or_folder.depth {
|
||||||
heap.extend(file_or_folder.children.iter().filter(|c| match min_size {
|
heap.extend(
|
||||||
|
file_or_folder
|
||||||
|
.children
|
||||||
|
.iter()
|
||||||
|
.filter(|c| match min_size {
|
||||||
Some(ms) => c.size > ms as u64,
|
Some(ms) => c.size > ms as u64,
|
||||||
None => !using_a_filter || c.name.is_file() || c.size > 0,
|
None => !using_a_filter || c.name.is_file() || c.size > 0,
|
||||||
}))
|
})
|
||||||
|
.filter(|c| if only_dir { c.name.is_dir() } else { true }),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
heap
|
heap
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-9
@@ -11,7 +11,9 @@ mod utils;
|
|||||||
|
|
||||||
use crate::cli::build_cli;
|
use crate::cli::build_cli;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::io::BufRead;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use sysinfo::{System, SystemExt};
|
||||||
|
|
||||||
use self::display::draw_it;
|
use self::display::draw_it;
|
||||||
use clap::Values;
|
use clap::Values;
|
||||||
@@ -19,6 +21,7 @@ use config::get_config;
|
|||||||
use dir_walker::{walk_it, WalkData};
|
use dir_walker::{walk_it, WalkData};
|
||||||
use filter::get_biggest;
|
use filter::get_biggest;
|
||||||
use filter_type::get_all_file_types;
|
use filter_type::get_all_file_types;
|
||||||
|
use rayon::ThreadPoolBuildError;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -89,14 +92,28 @@ fn get_regex_value(maybe_value: Option<Values>) -> Vec<Regex> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a list of lines from stdin or `None` if there's nothing to read
|
||||||
|
fn get_lines_from_stdin() -> Option<Vec<String>> {
|
||||||
|
atty::isnt(atty::Stream::Stdin).then(|| {
|
||||||
|
std::io::stdin()
|
||||||
|
.lock()
|
||||||
|
.lines()
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.expect("Error reading from stdin")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let options = build_cli().get_matches();
|
let options = build_cli().get_matches();
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
|
let stdin_lines = get_lines_from_stdin();
|
||||||
|
|
||||||
let target_dirs = options
|
let target_dirs = match options.values_of("inputs") {
|
||||||
.values_of("inputs")
|
Some(values) => values.collect(),
|
||||||
.expect("Should be a default value here")
|
None => stdin_lines.as_ref().map_or(vec!["."], |lines| {
|
||||||
.collect();
|
lines.iter().map(String::as_str).collect()
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
let summarize_file_types = options.is_present("types");
|
let summarize_file_types = options.is_present("types");
|
||||||
|
|
||||||
@@ -135,6 +152,8 @@ fn main() {
|
|||||||
|
|
||||||
let by_filecount = options.is_present("by_filecount");
|
let by_filecount = options.is_present("by_filecount");
|
||||||
let limit_filesystem = options.is_present("limit_filesystem");
|
let limit_filesystem = options.is_present("limit_filesystem");
|
||||||
|
let ignore_links = options.is_present("ignore_links");
|
||||||
|
let follow_links = options.is_present("dereference_links");
|
||||||
|
|
||||||
let simplified_dirs = simplify_dir_names(target_dirs);
|
let simplified_dirs = simplify_dir_names(target_dirs);
|
||||||
let allowed_filesystems = limit_filesystem
|
let allowed_filesystems = limit_filesystem
|
||||||
@@ -150,15 +169,13 @@ fn main() {
|
|||||||
filter_regex: &filter_regexs,
|
filter_regex: &filter_regexs,
|
||||||
invert_filter_regex: &invert_filter_regexs,
|
invert_filter_regex: &invert_filter_regexs,
|
||||||
allowed_filesystems,
|
allowed_filesystems,
|
||||||
|
ignore_links,
|
||||||
|
follow_links,
|
||||||
use_apparent_size: config.get_apparent_size(&options),
|
use_apparent_size: config.get_apparent_size(&options),
|
||||||
by_filecount,
|
by_filecount,
|
||||||
ignore_hidden: config.get_ignore_hidden(&options),
|
ignore_hidden: config.get_ignore_hidden(&options),
|
||||||
};
|
};
|
||||||
// Larger stack size to handle cases with lots of nested directories
|
let _rayon = init_rayon();
|
||||||
rayon::ThreadPoolBuilder::new()
|
|
||||||
.stack_size(usize::pow(1024, 3))
|
|
||||||
.build_global()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let iso = config.get_iso(&options);
|
let iso = config.get_iso(&options);
|
||||||
let (top_level_nodes, has_errors) = walk_it(simplified_dirs, walk_data);
|
let (top_level_nodes, has_errors) = walk_it(simplified_dirs, walk_data);
|
||||||
@@ -168,6 +185,7 @@ fn main() {
|
|||||||
false => get_biggest(
|
false => get_biggest(
|
||||||
top_level_nodes,
|
top_level_nodes,
|
||||||
config.get_min_size(&options, iso),
|
config.get_min_size(&options, iso),
|
||||||
|
config.get_only_dir(&options),
|
||||||
number_of_lines,
|
number_of_lines,
|
||||||
depth,
|
depth,
|
||||||
options.values_of("filter").is_some() || options.value_of("invert_filter").is_some(),
|
options.values_of("filter").is_some() || options.value_of("invert_filter").is_some(),
|
||||||
@@ -191,3 +209,19 @@ fn main() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_rayon() -> Result<(), ThreadPoolBuildError> {
|
||||||
|
let large_stack = usize::pow(1024, 3);
|
||||||
|
let mut s = System::new();
|
||||||
|
s.refresh_memory();
|
||||||
|
let available = s.available_memory();
|
||||||
|
|
||||||
|
if available > large_stack.try_into().unwrap() {
|
||||||
|
// Larger stack size to handle cases with lots of nested directories
|
||||||
|
rayon::ThreadPoolBuilder::new()
|
||||||
|
.stack_size(large_stack)
|
||||||
|
.build_global()
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ pub fn test_apparent_size() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apparent_size_output() -> Vec<String> {
|
fn apparent_size_output() -> Vec<String> {
|
||||||
// The apparent directory sizes are too unpredictable and system dependant to try and match
|
// The apparent directory sizes are too unpredictable and system dependent to try and match
|
||||||
let files = r#"
|
let files = r#"
|
||||||
0B ┌── a_file
|
0B ┌── a_file
|
||||||
6B ├── hello_file
|
6B ├── hello_file
|
||||||
|
|||||||
Reference in New Issue
Block a user