pax_global_header 0000666 0000000 0000000 00000000064 14112476455 0014523 g ustar 00root root 0000000 0000000 52 comment=93e75e363f7b8fef74b24214b61b96b3f92f7657
qdirstat-1.8/ 0000775 0000000 0000000 00000000000 14112476455 0013226 5 ustar 00root root 0000000 0000000 qdirstat-1.8/.github/ 0000775 0000000 0000000 00000000000 14112476455 0014566 5 ustar 00root root 0000000 0000000 qdirstat-1.8/.github/FUNDING.yml 0000664 0000000 0000000 00000000057 14112476455 0016405 0 ustar 00root root 0000000 0000000 custom: ["https://www.paypal.me/shundhammer"]
qdirstat-1.8/.gitignore 0000664 0000000 0000000 00000000026 14112476455 0015214 0 ustar 00root root 0000000 0000000 Makefile
.qmake.stash
qdirstat-1.8/LICENSE 0000664 0000000 0000000 00000043177 14112476455 0014247 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
qdirstat-1.8/README.md 0000664 0000000 0000000 00000126050 14112476455 0014511 0 ustar 00root root 0000000 0000000 # QDirStat
Qt-based directory statistics: KDirStat without any KDE -- from the author of
the original KDirStat.
(c) 2015-2021 Stefan Hundhammer
Target Platforms: Linux, BSD, Unix-like systems
License: GPL V2
Updated: 2021-08-28
## Screenshot
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-main-win.png)
_Main window screenshot - notice the multi-selection in the tree and the treemap_
## Overview
QDirStat is a graphical application to show where your disk space has gone and
to help you to clean it up.
This is a Qt-only port of the old Qt3/KDE3-based KDirStat, now based on the
latest Qt 5. It does not need any KDE libs or infrastructure. It runs on every
X11-based desktop on Linux, BSD and other Unix-like systems and of course in a
Docker container.
QDirStat has a number of new features compared to KDirStat. To name a few:
- Multi-selection in both the tree and the treemap.
- Unlimited number of user-defined cleanup actions.
- Properly show errors of cleanup actions (and their output, if desired).
- Configurable file categories (MIME types), treemap colors, exclude rules,
tree columns.
- Package manager support:
- Show what software package a system file belongs to.
- [Packages view](doc/Pkg-View.md) showing disk usage of installed software
packages and their individual files.
- [Unpackaged files view](doc/Unpkg-View.md) showing what files in system
directories do not belong to any installed software package.
- New views:
- Disk usage per file type (by filename extension).
- File size histogram view.
- [File Age View](doc/File-Age-Statistics.md)
- Free, used and reserved disk size for each mounted filesystem (like _df_)
See section [_New Features_](#new-features) for more details.
## Table of Contents
1. [Screenshot](#screenshot)
1. [Latest Stable Release](#latest-stable-release)
1. [Latest News](#latest-news)
1. [History](#history)
1. [Related Software](#related-software): KDirStat, WinDirStat, K4DirStat and more
1. [Motivation / Rant: Why?](#motivation--rant-why)
1. [Features](#features)
1. [MacOS X Compatibility](#macos-x-compatibility)
1. [Windows Compatibility](#windows-compatibility)
1. [Ready-made Packages](#ready-made-packages)
1. [QDirStat Docker Container](#qdirstat-docker-container)
1. [Building](#building)
1. [Contributing](#contributing)
1. [Troubleshooting](#troubleshooting)
1. [Further Reading](#further-reading)
1. [Packaging Status](#packaging-status)
1. [Donate](#donate)
## More Screenshots
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-file-type-stats.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-cleanup-output.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-column-config.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-locating-file-types.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-config-cleanups.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-config-mime.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-config-exclude.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-config-general.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-histogram.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-file-age-months.png)
_Full-size images and descriptions on the [Screenshots Page](https://github.com/shundhammer/qdirstat/blob/master/screenshots/Screenshots.md)_
-----------------------
## Donate
QDirStat is Free Open Source Software.
If you find it useful, please consider donating.
You can donate any amount of your choice via PayPal:
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EYJXAVLGNRR5W)
## Latest Stable Release
**QDirStat V1.8**
See the [release announcement](https://github.com/shundhammer/qdirstat/releases).
Download installable binary packages for various Linux distributions here:
[Ready-made packages](#ready-made-packages)
## Latest News
- 2021-08-28 **New stable release: 1.8**
**Summary:**
- New view: _File Age Statistics_
- Navigation history like in a web browser (_Back_, _Forward_)
- Bug fixes
- Some small improvements
**Details:**
- New view: _File Age Statistics_
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-file-age-years.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-file-age-months.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-file-age-long-ago.png)
This shows the number of files per year and/or per month that were last
modified in that year or month, together with the total size of those files
and a percent bar for both (number and total size).
- New documentation for that view: [File Age Statistics](doc/File-Age-Statistics.md)
- Navigation history for directories like in a web browser:
- New buttons _Back_ / _Forward_ in the tool bar
- Standard keyboard shortcuts `[Alt] [Cursor Left]` /
`[Alt] [Cursor Right]` like in all common web browsers
- Support for _Back_ / _Forward_ mouse buttons if the mouse has them
- History menu on those buttons (long press on the buttons) for the last 16
directories
- Internal restructuring and refactoring to keep the code maintainable
- Bug fixes:
- Fixed [GitHub issue #169](https://github.com/shundhammer/qdirstat/issues/169):
Shorten path components in the breadcrumb widget for insanely long paths.
- Now closing a left-over _Permissions error_ panel when refreshing from disk.
After the re-read, the permissions error may no longer be there.
- Small improvements:
- In the _Mounted Filesystems_ window, don't show inactive mounts managed
by the automounter anymore.
- In the _Open Directory_ window, automatically open the first directory
level if a path was clicked in the _Places_ list on the left, and scroll
the tree on the right so that path is at the top.
- Added a little margin to the left in the main window's tree view for the
_Size_ column so it looks now less cramped.
------------
- 2021-06-21 [QDirStat AppImage and why I don't like it](https://github.com/shundhammer/qdirstat/issues/168)
TL;DR:
- It's big and fat (113 MB)
- It's an outdated version (QDirStat 1.6.1 from 16 months ago)
- It doesn't even tell you what version it contains
- It still needs a fairly recent version of GLibc, so you can't run it on Ubuntu 18.04 LTS
- It's unclear if at least the libraries inside (e.g. the Qt libs) are up to date
-------------
_See [DevHistory.md](doc/DevHistory.md)
for older entries._
## History
This is just a rough summary. For more details, see [DevHistory.md](doc/DevHistory.md).
- 2021-08-28 New stable release: 1.8
- New view: _File Age Statistics_
- Navigation history like in a web browser (_Back_, _Forward_)
- Bug fixes
- Some small improvements
- 2021-04-05 New stable release: 1.7.1
- Added a "Discover" toplevel menu with actions to easily find
- the largest files
- the newest files
- the oldest files
- files with multiple hard links
- broken symbolic links
- sparse files
- Now showing the target of symbolic links in the details panel.
If the target does not exist, a **Broken Link** warning is also shown.
- Menu reorganization. The new toplevel menus are now:
File, Edit, View, Go To, Discover, Clean up, Help
- 2020-07-26 New stable release: 1.7
- Closing the gap between sizes reported by QDirstat and sizes reported by
the `du` command: Now also taking the allocated size into account.
- Now also displaying the allocated size where it makes sense.
- New "Mounted Filesystems" window showing output similar to the `df` command
(but without the cruft).
- New directory selection dialog showing all (real) filesystems.
- 2020-02-13 New stable release: 1.6.1
- Much better handling for "permission denied" errors while reading directories
- Now showing the exact byte size (134 495 994 Bytes instead of 128.3 MB)
upon mouse click
- New optional tree column "Oldest File" (not enabled by default)
- 2019-07-22 New stable release: V1.6
- New _packages_ view
- New _unpackaged files_ view
- Performance improvements while reading directories
- Vast Performance improvement for huge directories
(100.000+ entries in a single directory)
- 2018-11-07 New stable release: V1.5
- New _details_ panel
- Package manager support to show what software package a file belongs to
- New _breadcrumbs_ navigation
- Switchable tree layouts L1 / L2 / L3
- 2017-06-04 New stable release: V1.4
- New _file size statistics_ with histogram
- Shading for empty space in the treemap for lots of very small files
- 2017-03-05 New stable release: V1.3
- New _file type_ view
- Locate files of a certain type (filename extension) in the tree
- 2017-01-03 New stable release: V1.2
- Improved Btrfs subvolumes support
- 2016-10-31 New stable release: V1.1-Pumpkin
- Bug fixes
- Split up the config file into several ones
- 2016-05-16 First stable release: V1.0
- 2016-04-08 Beta 3 release
- 2016-03-20 Beta 2 release
- 2016-02-06 Beta 1 release
- 2015-11-28 QDirStat project start: Ported from the old KDE 3 KDirStat
- Predecessor: KDE 3 **KDirStat**
- 2006-06-01 KDirStat 2.5.3: The last KDE3 based version.
- 2003: Bernhard Seifert wrote **WinDirStat** based on the KDirStat idea of
coupling a tree view and a treemap and providing cleanup actions.
- 2003-01-05 KDirStat 2.3.3: Treemaps
- 2002-02-25 KDirStat 2.0.0: Complete rewrite for KDE 2 / Qt 2
- 2000-01-21 KDirStat 0.86 for KDE 1 announced: First public version.
## Related Software
### KDirStat and QDirStat
KDirStat was the first program of this kind (combining a traditional tree view
with a treemap), also written by the same author as QDirStat. It was made for
KDE 1 back in early 2000; later ported to KDE 2, then KDE 3.
QDirStat is based on that code, but made independent of any KDE libraries or
infrastructure, so it has much fewer library and package dependencies;
basically only the Qt 5 libs and libz, both of which most Linux / BSD machines
have installed anyway if there is any graphical desktop installed.
### WinDirStat and QDirStat
There are lots of articles and user forum comments about QDirStat being a "nice
Linux port of WinDirStat". Well, nothing could be further from the truth:
**WinDirStat is a Windows port of KDirStat**, the predecessor of QDirStat.
So it's the other way round: **The Linux version was there first**, and
somebody liked it so much that he wrote a Windows version based on that
idea. That's a rare thing; usually people port Windows originals to Linux.
See also https://windirstat.net/background.html and the WinDirStat "About"
dialog.
### QDirStat and K4DirStat
K4DirStat is a port to KDE 4 / Qt 4 of the old KDE 3 / Qt 3 KDirStat. QDirStat is
independent of that; it is based on the old KDE 3 KDirStat directly.
### Other
- Baobab
- Filelight
- ncdu
- du
See
[Disk Usage Tools Compared](https://github.com/shundhammer/qdirstat/wiki/disk-usage-tools-compared):
QDirStat vs. K4DirStat vs. Baobab vs. Filelight vs. ncdu (including benchmarks)
in the Wiki.
## Motivation / Rant: Why?
After having used KDE since its early days (since about 1998), I didn't like
the direction anymore that KDE has been taking. I loved KDE 1, KDE 2, KDE
3. When KDE 4 came along, it took me a long time to try to adopt it, and when I
did, I moved back to KDE 3 after a short while, then tried again with the next
release, moved back again -- several times.
I really tried to like it, but whenever I thought I tamed it to meet my
requirements, a new version came along that introduced yet another annoyance.
To name a few:
- A lot of things that used to be user configurable in KDE 3 are not
configurable anymore, and when you approach the KDE 4/5 developers about
that, they will tell you that this is intentional, and they do not intend to
bring those config options back. Well, thanks a lot; this is the Apple
approach where they think they know what is good for you, and you are just
too stupid.
- Konqueror as the old central tool is as good as dead. It's still there as an
alternate file manager (for those who find it), but the primary one is the
dumbed-down Dolphin that I consider unusable: It's only useful for complete
newbies, not for power users. The web browser part of Konqueror is so
outdated that you can't do much with it with most modern web sites, so the
great integration of web and local file manager that was the major strong
point of Konqueror (and thus KDE) no longer exists.
- I don't like the fact that I can't simply put icons on my desktop anymore --
no, I have to create a plasmoid first as a container, and those things keep
doing weird stuff that drives every user crazy. With one false move of your
mouse, it might be gone, change shape, move to another place or whatever.
- I also don't like the desktop search that eats resources like there is no
tomorrow (disk space, disk I/O, CPU usage) and that for all practical
purposes you can't get rid of.
- I don't like the fact that the mail client relies on that MySQL based
framework called _Akonadi_ that is not only resource-hungry, but also so
fragile that I had to use the _akonadiconsole_ lots of times just to bring it
back to life. Seriously, if I as a Linux system developer have a hard time
doing that, what is a normal user expected to do?
- Activities vs. multiple desktops. I tried to use both, but they don't
integrate well. The desktops previewer is far inferior to the old one from
KDE3: Only monochrome rectangles, no real preview. The activities plasmoid
keeps rearranging my carefully placed and named activities at random. WTF?!
- Everything is so fragmented that not even the naming is clear anymore. What
used to be KDE is now a jumble of the KF Framework, the KF libs, the KF apps
and the Plasma desktop. Yeah, great job, folks; people used to know what KDE
stood for. Nobody knows what the hell all those components are, and neither
does anybody care anymore. You paved your way to oblivion with buzzwords.
Great marketing strategy for gaining more visibility!
Then the next generation KDE arrived, _Plasma 5_. When I was force-migrated to
it at work with the _SUSE Tumbleweed_ rolling release, the experience was so
bad that I moved to the _Xfce_ Desktop.
Now every time I started my own KDirStat, it started about a dozen KDE
processes along with it -- processes that it needs only for minor things like
loading icons or translations. I really don't need or want that.
So it was time to make KDirStat self-sufficient; it never used that much of all
the KDE infrastructure anyway. Time to make a pure Qt-based and self-sufficient
QDirStat.
And while I was at it, I took the chance to add some features that I had wanted
for a long time, yet I had never gotten myself to start working on:
- Multi-selection in the directory tree so you can delete several files at
once.
- Remove limitations like having only a fixed number of user-defined cleanup
actions.
- Properly show the output of cleanup actions, in particular when they reported
errors.
- Make treemap colors configurable: Use custom colors and match them to
user-defined filename extensions.
- Move away from the arcane KDE build system: Back with KDE 1/2/3 it was the
_Autotools_ with custom KDE extensions that only a handful people in the
world really understood (I was not among them), later _CMake_ which is little
better, just differently confusing.
Yes, there is a Qt4 / Qt5 port of KDirStat called K4DirStat. K4DirStat is an
independent project that started when I had not worked on the old KDirStat for
a long time (my last KDirStat release had been in mid-2006).
QDirStat is based on that same code from the 2006 KDirStat. It's an 80% rewrite
using a lot of newer Qt technologies. And there was a lot of cleaning up that
old code base that had been long overdue.
## Features
### New Features
- Multi-selection:
- Both views (the tree and the treemap) now support _extended_ selection,
i.e. you can select more than one item. This was the most requested feature
for the last KDirStat. Now you can select more than one item at the same
time to move it to the trash can, to directly delete it or whatever.
- Tree view:
- Shift-click: Select a range of items.
- Ctrl-Click: Select an additional item or deselect a selected one.
- Treemap:
- Ctrl-Click: Select an additional item or deselect a selected one.
- The current item is highlighted with a red rectangle, all other selected
ones with a yellow rectangle. If the current item is not also selected,
it has a dotted red outline.
- Proper output of cleanup actions with different colors for the commands that
are executed, for their output and for error messages (see screenshot
above). That output window can be configured to always open, to open after a
certain (configurable) timeout, or only if there are error mesages -- or not
at all, of course. If things go wrong, you can kill the external command
started by the cleanup action from there. You can zoom in and out (increase
or decrease the font size) as you like.
- File type statistics window. WinDirStat has it, and users wanted it in
QDirStat, too. Since filename extensions (suffixes) don't have as much
semantics in Linux/Unix systems as they do in Windows, many files are
categorized as "Other". This is a known limitation, but it's a limitation of
the whole concept of using suffixes to categorize files by type. And no,
checking file headers for magic byte sequences like the "file" command does
is not an option here; QDirStat would have to do that for (at least) all the
30,000+ files typically listed under the "Other" category. So we'll have to
live with that limitation.
- Locate files by file type window. If you double-click on any of the filename
extensions (suffixes) in the file type statistics window, you will get
another window that lists all the directories that contain files of that type
including the number and total size of those files. You can double-click each
of those lines, and that directory will open in the main window with the
files of that type preselected so you can start cleanup actions like moving
them to trash or converting them to a better format (.bmp -> .png)
immediately.
- File size statistics window with histogram, percentiles, buckets and a lot of
documentation that everybody should be able to understand. Even if (or,
better yet, in particular if) your math teacher or statistics professor never
explained it properly, please have a look at it.
- File age statistics window: This lists the number and total size of changed
files by years and for recent (13-24) months. You can see in what time frame
there was any activity (i.e. any changes) in a directory tree, i.e. when it
last was in active use; or if it might be a good candidate to be moved to
archive media.
- Packages view: Show installed packages and their files in the tree. Supported
for all Linux distributions using any of _dpkg_, _rpm_, _pacman_ as their
low-level package manager or any higher-level package manager like _apt_,
_zypper_ etc.; more details at [Pkg-View.md](doc/Pkg-View.md).
- Unpackaged files view: Show a directory tree, but ignore all files that
belong to an installed software package. Those ignored files are displayed in
a special branch __ in the tree view, and they are not displayed at
all in the treemap. This is useful to find files that were manually
installed by a `sudo make install` command. More details at
[Unpkg-View.md](doc/Unpkg-View.md).
- New macros to use in cleanup actions:
- %d : Directory name with full path. For directories, this is the same as
%p. For files, this is their parent directory's %p.
- %terminal : Terminal window application of the current desktop; one of
"konsole", "gnome-terminal", "xfce4-terminal", "lxterminal", "eterm".
The fallback is "xterm".
- %filemanager : File manager application of the current desktop; one of
"konqueror", "nautilus", "thunar", "pcmanfm". The fallback is "xdg-open".
- Which desktop is used is determined by the _$XDG_CURRENT_DESKTOP_ environment
variable. Users can override this with the _$QDIRSTAT_DESKTOP_ environment
variable, so you can get, say, the Xfce terminal or file manager despite
currently running KDE if you set
export QDIRSTAT_DESKTOP="Xfce"
- Of course, you can still simply use your favourite file manager if you simply
change %filemanager in the default "Open File Manager Here" cleanup action to
the command to start it.
- You can now select the shell to use for the cleanup commands:
- $SHELL (the user's login shell) - using the same environment, syntax and
wildcard etc. behaviour of the shell the user is used to.
- /bin/bash for well-defined behaviour for wildcards etc.
- /bin/sh as a last resort (which might be a simplistic _dash_ on Ubuntu).
- Mouse actions in the treemap window:
- Left click: Select item and make it the current item.
- Right click: Open the context menu with cleanup actions and more.
- Ctrl+Left click: Add item to selection or toggle selection.
- Middle click: Select the current item's parent. Cycle back at toplevel.
- Double click left: Zoom treemap in.
- Double click middle: Zoom treemap out.
- Mouse wheel: Zoom treemap in or out.
- You can configure what columns to display in the tree view and in which
order. The only thing that is fixed is the "Name" column which is always
there and always the first (leftmost). Use the context menu in the tree
header to unlock column widths. Drag columns to the left or right to change
their order.
- Exclude rules are now greatly simplified. They no longer always get the
entire path to match which requires quite complex regexps; by default, they
only get the last path component -- i.e., no longer
"/work/home/sh/src/qdirstat/src/.git", but only ".git". You can now even tell
the exclude rule to use a simplified syntax: "FixedString" or "Wildcard" in
addition to the normal "RegExp". The old behaviour (matching against the full
path) is still available, though.
- Configuration dialog for exclude rules -- see screenshots.
- Subvolume detection for Btrfs. Btrfs subvolumes are just ordinary mount
points, so normally QDirStat would stop scanning there, leaving a large part
of a Btrfs partition unaccounted for. But for each mount point found while
scanning a directory tree, QDirStat checks /proc/mounts or /etc/mtab if it
has the same device name as its parent directory, and if yes, considers it a
subvolume and continues scanning.
- Actions to go one directory level higher or to the toplevel: Context menu and
menu "Go To" -> "Up One Level" or "Toplevel". This is useful if you clicked
on a file in the treemap that is deep down in some subdirectory, and you want
to know what subdirectory that is: Simply click "Go Up" twice (the first
click will get you to the pseudo subdirectory, the second one to the
real one).
- Open all tree branches up to a certain level and close all other ones: Menu
"View" -> "Expand Tree To Level" -> "Level 0" ... "Level 9".
- The total sum of the selected items (subtrees) is displayed in the status
line if more than one item is selected.
- Icons are now compiled into the source thanks to Qt's resource system; now
it's just one binary file, and nothing will go missing. No more dozens of
little files to handle.
- The build system is now Qt's _QMake_. I got rid of that _AutoTools_
(Automake, Autoconf, Libtool) stuff that most developers find intimidating
with its crude M4 macro processor syntax. QMake .pro files are so much
simpler, and they do the job just as well. And no, it will definitely never
be _CMake_: I don't like that thing at all. It's just as much as a PITA as
the AutoTools, just not as portable, no usable documentation, it's changing
all the time, and those out-of-source builds are a royal PITA all on their
own with constantly having to change back and forth between source and build
directories.
- QDirStat now has its own log file. It now logs to
`/tmp/qdirstat-$USER/qdirstat.log` (where $USER is your Linux user name).
No more messages on stdout that either clobber the shell you started the
program from or that simply go missing.
- No longer depending on dozens of KDE libs and a lot of KDE infrastructure; it
now only requires Qt which is typically installed anyway on a Linux / BSD /
Unix machine with any X11 (graphical) desktop.
- It should still compile and work with Qt4. We now have a contributor who is
very interested in that (Michael Matz), so it should be possible to maintain
this compatibility.
- Slow down display update from 333 millisec (default) to 3 sec (default) with
`qdirstat --slow-update` or `qdirstat -s`. The slow update interval can be
customized in `~/.config/QDirStat/QDirStat.conf`:
```ini
[DirectoryTree]
SlowUpdateMillisec = 3000
```
### Old Features
Features ported from the old KDirStat:
- Fast and efficient directory reading.
- Not crossing filesystem boundaries by default so you can see what eats up
all the disk space on your root filesystem without getting distorted numbers
due to all the other filesystems that are mounted there. If you absolutely
wish, you can use "Continue reading at mount point" from the context menu or
from the "File" menu -- or configure QDirStat to always read across file
systems.
- Efficent memory usage. A modern Linux root filesystem has well over 800,000
objects (files, directories, symlinks, ...) and about 100,000 directories.
This calls for minimalistic C++ objects to represent each one of
them. QDirStat / KDirStat do their best to minimize that memory footprint.
- Hierarchical tree view that displays accumulated sums in each branch,
together with a percent bar so you can see at a glimpse how the
subdirectories compare with each other.
- All numbers displayed human readable -- e.g., 34.4 MB instead of 36116381
Bytes.
- All size units are 1024-based, i.e. 1 kB = 1024 Bytes; 1 MB = 1024 kB; 1 GB =
1024 MB.
- In the tree, also displaying the exact byte size as the context menu (right
click).
- Each tree level uses another color for that percent bar so you can easily
compare subdirectories even if some of them are opened in the tree.
- If a directory has files and subdirectories, all files in that subdirectory
are grouped into a pseudo directory (called _dot entry_ in the
QDirStat sources) so you can compare the disk usage of files on that
directory level with the subdirectories.
- Displaying the latest modification time of any object in each branch. You can
instantly see in what subdirectory where any changes lately. You can sort by
this column, of course.
- Treemap display. Treemaps are a way to visualize hierarchical data
structures, invented by Ben Shneiderman. Basically, the hierarchy is
flattened and each level grouped in a rectangle, inside which it is again
subdivided in rectangles. The area of each rectangle corresponds to the size
of each item or subdirectory. For the purposes of QDirStat, it is enough to
know that a large blob corresponds to a large file; you can instantly see
where large ISOs or movies are.
- You can zoom the treemap in and out (Ctrl + / Ctrl - / mouse wheel / menu /
tool bar) to see more details of directories that are otherwise dominated by
larger ones.
- You can move the boundary between treemap and tree view up and down as you
like. You can also get rid of the treemap completely (menu "Treemap" -> "Show
Treemap" or F9 key)
- Treemap and tree list view communicate. Select an item in one view, and it is
also selected in the other. If you click on that large blob in the treemap,
it is located in the tree view, all branches up to its directory are opened,
and the tree view scrolls to that item.
- Cleanup actions. Once you know what is consuming the disk space, you can
start cleanup actions from within QDirStat to reclaim disk space - or to
investigate further if you can safely delete a file. You can create your own
cleanup actions (as many as you like), and there are some predefined ones:
- Open file manager here. This will start a file manager in the directory of
the current item. QDirStat tries its best to guess the name of the relevant
file manager application for the current desktop, based on the
$XDG_CURRENT_DESKTOP environment variable. You can override this with the
$QDIRSTAT_DESKTOP environment variable.
- Open terminal window here. In most cases, this is much easier than to
navigate to that directory with 'cd' in an already open terminal window and
using tab-completion numerous times. As with the file manager application,
QDirStat tries its best to guess the name of the relevant terminal window
application for the current desktop.
- Move to trash bin. QDirStat has its own implementation of the XDG trash
specification.
- Delete immediately.
- Compress: Create a compressed tar archive from a directory and then delete
the directory.
- Delete junk files: Backup files left behind by editors, core dumps.
- All predefined cleanup actions are fully configurable, of course. You can
change any of them, disable them, or delete them.
- You can copy the complete path of the selected file or directory to the
system clipboard and paste it to another application.
- Reading and writing cache files:
- This is mostly meant for remote servers in some server room somewhere:
Rather than installing the Qt and X11 runtime environment and running
QDirStat over remote X (ssh with X forwarding), you can run the supplied
_qdirstat-cache-writer_ Perl script on the server, copy the resulting cache
file to your desktop machine and view the content there with QDirStat.
- For large directories (archives etc.) that don't change that much, you can
also generate a QDirStat cache file (either with the Perl script or with
QDirStat itself) and save it to that corresponding directory. If QDirStat
finds a file .qdirstat.cache.gz in a directory, it checks if the toplevel
directory in that cache file is the same as the current directory, and if
it is, it uses the cache file for that directory rather than reading all
subdirectories from disk. If you or the users of that machine use QDirStat
often, this might take a lot of I/O load from the server.
- If you use the '-l' option of the qdirstat-cache-writer script, it uses the
long file format with a complete path for each entry, so you can use the
_zgrep_ command with it as a replacement for the _locate_ command.
- The KDirStat / QDirStat file format is well documented and very simple. It
seems to be used by a number of admins and some backup software.
See also the specification in the doc/ directory:
https://github.com/shundhammer/qdirstat/blob/master/doc/cache-file-format.txt
- You can specify a cache file to read directly at the command line:
```
qdirstat --cache cache-file
```
- Other command line options: See
```
qdirstat --help
```
### Features that are Gone
(Compared to the old KDirStat)
- Pacman animation
- KIO slave support
- Feedback form
- KPacman: That was that PacMan animation wile reading directory reading. This
is gone now. KPacMan looked out of place pretty soon after it got to KDirStat
due to Qt styles doing fancy rendering of widget backgrounds with gradients
etc. I know that it does have its fans, but it's unrealistic to get this
back without breaking the menu bar rendering.
- KioDirReadJob: Network-transparent directory reading for network protocols
like FTP, HTTP, Fish (ssh-based). This depended on KDE's KIO slaves, so this
functionality is gone now without KDE. That's a pity, but this is a little
price to be paid to avoid the rest of the hassle with using the KDE libs.
- KFeedback: That was that form where users could tell their opinion about
KDirstat. But that was not used that often anyway - not nearly enough to
justify the effort that has gone into that part. And the KDE usability
people, like usability people generally tend to do, first discussed that to
death and then decided they didn't want anything like that in general in KDE
applications. So be it.
- KActivityTracker: That was a supporting class for KFeedback that kept track
of how much a user was using the program and after a while (when it was
determined that it made sense) asked if the user wouldn't like to give his
feedback about the program.
Don't you all just hate those dumbass web designers who tell you to do a
survey how much you like their grand web page before you even had a chance to
look at it? Shove a pop-up up your face covering the stuff you are
interesting in with their self-loving marketing bullshit? -- KActivityTracker
was made to avoid exactly this: Ask the user only once you know that he
actually used the program for a while.
## MacOS X Compatibility
There is some experimental support for MacOS X, but it's really only that: Experimental.
I was amazed to find that it doesn't take more than the normal "qmake" and then
"make" to build QDirStat for MacOS X. We (Sonja Krause-Harder and I) did some
basic testing, and it seems to work.
The cleanups may need some adaptation, but this is something that might even be
configured by the user.
If anybody wants to give it a try, download Qt for MacOS X, install it, open a
shell window, search the _qmake_ command:
find . -name qmake
Add this to your $PATH, then do the normal
qmake
make
Not sure how well "make install" works, though.
**_Be advised that QDirStat on MacOS X is purely experimental at this stage._**
There is no support. If you try this, you are on your own. Even more so than
with the other platforms, you will have to make sure that your Qt build
environment is set up correctly.
_There be dragons._ ;-)
### Architecture maintainer wanted for QDirStat for MacOS X
If you are a developer with some prior C++ and Qt knowledge on the MacOS X
platform and you'd like to see QDirStat working there, please consider joining
the team.
## Windows Compatibility
There is no native Windows version, but you can use the
[docker](#qdirstat-docker-container) container.
Other than that, there is [WinDirStat](https://windirstat.info/).
There are currently no plans for doing a native Windows port.
Directory reading might be quite easy to replace for Windows; we don't have
that problem with devices and crossing filesystems on that platform.
But the cleanups might be a challenge, "move to trash" works completely
differently, and we'd need an installer for a Windows version.
So, for the time being, use the [docker](#qdirstat-docker-container) or
[WinDirStat](https://windirstat.info/) instead.
WinDirStat is a close relative to the KDirStat family anyway; the author had
liked KDirStat on Linux so much that he decided to write a Windows clone and
called it WinDirStat.
## Ready-made Packages
[](https://repology.org/metapackage/qdirstat/versions)
### openSUSE / SUSE Linux Enterprise
QDirStat packages for openSUSE Tumbleweed / Leap (15.x, 42.x) and SLE (15, 12):
- Download page for the [**latest stable release**](https://software.opensuse.org/download/package?project=home:shundhammer:qdirstat-stable&package=qdirstat)
- Download page for the [**current development version** (git master)](https://software.opensuse.org/download/package?project=home:shundhammer:qdirstat-git&package=qdirstat)
Since this version is in development, it may be not quite as stable and
reliable as the latest official stable release, although the QDirStat
developers try their best to keep it as stable as possible.
### Ubuntu
https://packages.ubuntu.com/search?keywords=qdirstat&searchon=names
### Debian
https://packages.debian.org/search?keywords=qdirstat
### Fedora
https://apps.fedoraproject.org/packages/qdirstat/builds/
## QDirStat Docker Container
@jlesage kindly provides a
[docker container for QDirStat](https://hub.docker.com/r/jlesage/qdirstat).
That makes QDirStat usable even on non-Linux / non-Unix systems such as Windows
or MacOS X.
Docker is basically a virtualized environment to run software that was designed
for a different operating system.
It is very much like using VmWare or VirtualBox, but with much less overhead:
You don't have to install that other system first and then on top of that the
application that you really want to run. A docker container contains everything
that is needed, and it is preconfigured for that application.
### How to use Docker on Windows
- Download and install [Docker Desktop for Windows](https://hub.docker.com/editions/community/docker-ce-desktop-windows)
- Use the Docker Desktop for Windows to launch the
[QDirStat Docker](https://hub.docker.com/r/jlesage/qdirstat) (as a Linux container)
- Adapt the command line so the disk that you want to explore is used
More information:
- https://docs.docker.com/docker-for-windows/install/
- https://docs.docker.com/get-started/
## Building
_Notice that for most mainstream Linux or BSD distributions you don't have to
build your own; you can simply install a ready-made package from your normal
package manager._
### Build Environment
Make sure you have a working Qt 5 build environment installed. This includes:
- C++ compiler (gcc recommended)
- Qt 5 runtime environment
- Qt 5 header files
- libz (compression lib) runtime and header file
If anything doesn't work, first of all **make sure you can build any of the
simple examples supplied with Qt**, e.g. the
[calculator example](http://doc.qt.io/qt-5/qtwidgets-widgets-calculator-example.html).
#### Ubuntu
Install the required packages for building:
sudo apt-get install build-essential qtbase5-dev zlib1g-dev
Dependent packages will be added automatically.
Recommended packages for developers:
sudo apt-get install qttools5-dev-tools qtbase5-doc qtbase5-doc-html qtbase5-examples
See also
http://askubuntu.com/questions/508503/whats-the-development-package-for-qt5-in-14-04
If you also have a Qt4 development environment installed, select the desired
one via _qtchooser_:
sudo apt-get install qtchooser
export QT_SELECT="qt5"
#### SUSE
Install the required packages for building:
sudo zypper install -t pattern devel_C_C++
sudo zypper install libQt5Widgets-devel libqt5-qttools zlib-devel
If you also have a Qt4 development environment installed, make sure that the
Qt5 version of 'qmake' is the first in your $PATH:
export PATH=/usr/lib64/qt5/bin:$PATH
### Compiling
Open a shell window, go to the QDirStat source directory, then enter these
commands:
qmake
make
### Installing
sudo make install
or
su -c make install
### Install to a Custom Directory
The default setup installs everything to `/usr`. To install to another
directory, set `INSTALL_PREFIX` during `qmake`.
qmake INSTALL_PREFIX=/usr/local
Beware that some things might not work as expected; for example, you will not
get a `.desktop` file in the proper place to make QDirStat appear in any menus
in your graphical desktop environment or in the file manager. You will need to
copy the `.desktop` file manually to whatever directory your graphical desktop
environment uses somewhere in your home directory. Similar with the application
icon used in that `.desktop` file.
## Contributing
See file [Contributing.md](doc/Contributing.md)
and [GitHub-Workflow.md](doc/GitHub-Workflow.md)
## Troubleshooting
### Can't Move a Directory to Trash
See file [Troubleshooting.md](doc/Troubleshooting.md)
## Further Reading
- Original [KDirStat](http://kdirstat.sourceforge.net/) ([source code](https://github.com/shundhammer/kdirstat))
- [K4Dirstat](https://bitbucket.org/jeromerobert/k4dirstat/wiki/Home) ([source code](https://bitbucket.org/jeromerobert/k4dirstat/src))
- [WinDirStat](https://windirstat.info/) (for Windows)
- [Disk Usage Tools Compared: QDirStat vs. K4DirStat vs. Baobab vs. Filelight vs. ncdu](https://github.com/shundhammer/qdirstat/wiki/disk-usage-tools-compared) (including benchmarks)
- [XDG Trash Spec](http://standards.freedesktop.org/trash-spec/trashspec-1.0.html)
- [Spatry's QDirStat Review on YouTube](https://www.youtube.com/watch?v=ysm4-x_5ftI)
Of course, don't forget to check out the [doc directory](doc/).
## Packaging Status
Repology: QDirStat versions in Linux / BSD distributions:
[](https://repology.org/metapackage/qdirstat/versions)
(click for details)
## Donate
QDirStat is Free Open Source Software.
If you find it useful, please consider donating.
You can donate any amount of your choice via PayPal:
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EYJXAVLGNRR5W)
qdirstat-1.8/doc/ 0000775 0000000 0000000 00000000000 14112476455 0013773 5 ustar 00root root 0000000 0000000 qdirstat-1.8/doc/Btrfs-Free-Size.md 0000664 0000000 0000000 00000015236 14112476455 0017173 0 ustar 00root root 0000000 0000000 # Btrfs and Free Size Reporting
Btrfs is a Linux filesystem with advanced features like copy-on-write and
snapshots. While that is very convenient to go back to a previous state of the
system after botched package upgrades or manual configurations, it also comes
at a cost: It consumes disk space.
However, disk space used in that way is **not** reported to the usual tools
like the `df` command or even system calls like `statfs()`; Btrfs only reports
disk space used by files and directories to them.
So it can easily happen (this is actually quite a common problem) that the `df`
command (or other similar commands that rely on Btrfs reporting sizes properly)
tells you that your Btrfs filesystem still has 15 GB of its total 30 GB
available, yet you get a "no space left on device" error: The remaining space
might be taken by filesystem snapshots and/or by copy-on-write.
One might argue that Btrfs is blatantly lying about its free space, that it
should really report the real free disk space to the underlying system calls
like `statfs()`, so the tools using that system call can give the user the real
information and not just some bogus numbers.
## Helpful Btrfs Commands
To find out more about available disk space on a Btrfs, you need to use special
Btrfs commands, and they _all_ require root permissions (which is one reason
why QDirStat does not do that internally).
Yes, this is most annoying.
Yes, this could be done better; a **lot** better.
Yes, this problem has been known for many years, and no progress is visible in
that area.
### btrfs fi usage
```
sudo btrfs filesystem usage /mybtrfs
Overall:
Device size: 40.00GiB
Device allocated: 30.06GiB
Device unallocated: 9.94GiB
Device missing: 0.00B
Used: 26.80GiB
Free (estimated): 10.92GiB (min: 5.95GiB)
Data ratio: 1.00
Metadata ratio: 2.00
Global reserve: 63.12MiB (used: 0.00B)
Multiple profiles: no
Data,single: Size:25.00GiB, Used:24.02GiB (96.07%)
/dev/sda2 25.00GiB
Metadata,DUP: Size:2.50GiB, Used:1.39GiB (55.69%)
/dev/sda2 5.00GiB
System,DUP: Size:32.00MiB, Used:16.00KiB (0.05%)
/dev/sda2 64.00MiB
Unallocated:
/dev/sda2 9.94GiB
```
This can be slightly abbreviated to
```
sudo btrfs fi usage /mybtrfs
```
_Notice that all Btrfs commands always need the mount point as the argument, not the device._
### btrfs fi df
```
sudo btrfs filesystem df /mybtrfs
Data, single: total=25.00GiB, used=24.02GiB
System, DUP: total=32.00MiB, used=16.00KiB
Metadata, DUP: total=2.50GiB, used=1.39GiB
GlobalReserve, single: total=63.12MiB, used=0.00B
```
Shorter: `sudo btrfs fi df /mybtrfs`
### btrfs fi show
```
sudo btrfs filesystem show /mybtrfs
Label: 'mybtrfs' uuid: a0be3e1e-d127-45b8-85d6-...
Total devices 1 FS bytes used 25.41GiB
devid 1 size 40.00GiB used 30.06GiB path /dev/sda2
```
Shorter: `sudo btrfs fi show /mybtrfs`
### btrfs balance
https://btrfs.wiki.kernel.org/index.php/FAQ#What_does_.22balance.22_do.3F
Greatly simplified, this is the Btrfs counterpart of defragmenting the
filesystem: It cleans up metadata.
How to invoke it, however, seems to be some black magic, and there are lots of
guides out on the web; google for "btrfs balance". Some search results:
- https://www.thegeekdiary.com/how-to-re-balancing-btrfs-to-free-disk-space/
- http://marc.merlins.org/perso/btrfs/post_2014-05-04_Fixing-Btrfs-Filesystem-Full-Problems.html
## Background Information
### Snapshots
A main reason for using Btrfs in the first place is using snapshots before
critical changes to the system, such as software package upgrades: Before
installing upgraded package versions, the old system state is saved into a
_snapshot_, then the upgrade is performed. If the upgrade resulted in problems,
you can _roll back_ to a previous snapshot.
This can be done manually or with tools such as _snapper_. On SUSE Linux, a
snapshot is created with _snapper_ for every set of package upgrades or when
certain system administration tasks are done with _YaST_, typically even a
"pre" snapshot before the action is performed and a "post" snapshot immediately
afterwards.
Since Btrfs uses CoW, this is not nearly as expensive as one might think: Only
changed disk blocks need to be actually copied, not the complete filesystem.
However, as snapshots accumulate, so does disk space usage. This is why
_snapper_ has multiple strategies to clean up snapshots. Even so, you can run
out of disk space if you don't keep track of your snapshots, in particular if
you use a rolling release like openSUSE Tumbleweed with regular updates every
few days, and free space on your Btrfs root filesystem wasn't too plentiful to
begin with.
You can use the `snapper` command line (`snapper ls`, `snapper rm`) or the YaST
snapper module to monitor and manage snapshots. If you find you have to clean
up snapshots manually very often, consider using a different automatic strategy
for cleaning them up.
See also `man snapper`.
### CoW (Copy-on-Write)
https://en.wikipedia.org/wiki/Copy-on-write
Btrfs by default uses CoW (copy-on-write) for write access: It can share disk
blocks among different _subvolumes_ or _snapshots_ (which are technically
little different from subvolumes). As long as the content of a file and its
disk blocks is identical between subvolumes or snapshots, there is no need to
copy all the blocks of that file, so all that Btrfs does is add a new reference
to it and increase a reference count.
When data are written to that file, however, the old data need to be saved to
remain available in the old version to that subvolume or snapshot; so at that
moment, the affected disk blocks are really copied, and only then new content
is written to the file.
This is a very efficient way of keeping copies of older data so you can go back
to a previous snapshot: Most data are identical between snapshots, so there is
no need to really copy them; a reference count does just nicely.
However, this can be a nightmare for data that change all the time, and change
in random places: Binary database files for RDBMS such as MariaDB (formerly
MySQL) are a typical example. Also, you never want to roll back such files
anyway because you cannot guarantee consistency of such binary data; they need
to be exempt from snapshots.
This is why there are _subvolumes_ with different mount options such as `noCoW`
for certain directories; not only would it be wasteful to keep older versions
of such files, it would also be counterproductive and endanger consistency.
## Further Reading
- https://www.linuxlinks.com/btrfs/
- https://btrfs.wiki.kernel.org/index.php/FAQ#How_much_free_space_do_I_have.3F
- https://btrfs.wiki.kernel.org/index.php/SysadminGuide
- https://en.opensuse.org/SDB:BTRFS qdirstat-1.8/doc/Building.md 0000664 0000000 0000000 00000000161 14112476455 0016050 0 ustar 00root root 0000000 0000000 # Building QDirStat
See [main document](https://github.com/shundhammer/qdirstat/blob/master/README.md#building)
qdirstat-1.8/doc/Contributing.md 0000664 0000000 0000000 00000015764 14112476455 0017001 0 ustar 00root root 0000000 0000000 # Contributing to QDirStat
Contributions are welcome. Please follow the rules and guide lines in this
document:
## Guide Lines
Use the same style as the existing code.
Indentation is 4 blanks. One tab is 8 blanks. Do not indent with single tabs
for each indentation level and thus fuck up everybody else's editor. Letting
the editor automatically replace 8 blanks with a tab is okay, but indentation
level is still 4 blanks.
Brace style is braces **always** on a new line. Use blanks after opening and
before closing parentheses:
if ( someCondition )
{
doSomething( arg1, arg2 )
}
**No** K&R style indentation:
if (someCondition) { // WRONG!!!
doSomething(arg1, arg2) // WRONG!!!
}
Use blank lines liberally. No Rubocop-style code.
Use CamelCase for classes and camelCase for variables. Do not use
snake_case. Prefix member variables with an underscore: _someValue. Prefix its
setter with Set...(), use only the name (someValue()) for the getter, **Not**
getSomeValue():
private:
SomeType _someValue; // member variable
public:
const & SomeType someValue() const; // getter
void setSomeValue( const SomeType & newValue ); // setter
Use a const reference for the setter parameter and the getter return type for
nontrival data types (everything beyond a pointer or an int etc.), and the type
directly otherwise. Use your common sense.
Use Qt types whereever possible. Do not introduce types that are also available
in a Qt version. In particular, do not use STL or Boost types unless there is
no other reasonable way.
For Qt dialogs, use Qt Designer forms whenever possible. I know that many Qt
developers don't like Qt Designer (typically based on bad experiences years
back), but it's really worthwhile to use it. This avoids having tons of dumb
boilerplate code just for creating widget trees.
### Documenting Classes and their Methods
Document classes and their methods in their header file. Document them
immediately. If you don't do it right away, it will never happen. Don't wait
for somebody else to do that for you - nobody will be willing to do the
inconvenient part of the job for you.
Undocumented stuff will mercilessly be rejected.
In my 30+ years of programming I came to the conclusion that it helps immensely
to write down a function name in the header file and **immediately** write its
documentation:
- What does it do? (Do not just repeat the function name! **Explain** what it does!)
- What are the parameters?
- What does it return?
- In particular for functions returning bool: Which case returns 'true', which
case returns 'false'?
- What happens in fringe cases? (returning NULL pointer?)
- If the function creates any objects: Who owns them?
- Does the function transfer ownership of any objects it gets pointers to (as
parameters) to itself or wherever?
If you do that right, you might as well leave the implementation to somebody else.
**Do not** insert any doc template without content before each function.
This is worse than no documentation at all: Everybody has to wade through tons
of useless empty forms that don't contain any content whatsoever.
Been there. Done that. Hated it.
Be careful when copying and pasting documentation from some other place.
Misleading documentation is worse than no documentation at all.
### Legalese in the Sources
**Do not** copy 30+ lines of legalese bullshit into any source file. One line
in the header like
License: GPL V2 - see file LICENSE
is plenty. Seriously, what are those people thinking who put all that legalese
into source files? Sure, they listened to spineless corporate lawyers who just
want to make sure. But those lawyers are not going to have that crap smack up
their faces every time they open a file for editing. We developers do.
You lawyers out there, can you hear me? **This crap is in the way! Nobody wants
to read that!** It's in the way of people trying to do their jobs! We could
construct a harassment case from this!
### The GitHub Workflow
See separate document [GitHub-Workflow.md](https://github.com/shundhammer/qdirstat/blob/master/doc/GitHub-Workflow.md)
### Getting Help for Contributors
- Use the Qt reference documentation.
- Install and study carefully the available Qt examples for reference.
- Read the (extensive!) documentation in the QDirStat header files.
- Use Stack Overflow.
- Use Google.
- Make sure you can build a basic Qt program.
- Make sure you have the compiler and other developer tools set up correctly.
- Make sure you have the relevant -devel (SUSE) or -dev (Ubuntu/Debian)
packages installed.
If you did all of the above (and only then!) and still couldn't figure out
what's wrong:
- Use IRC (#qdirstat on irc.freenode.net; fallback: contact HuHa in #yast on
freenode IRC)
- Write a mail
It is a matter of professional courtesy to first use what is freely available
on the web before you consume somebody else's time and expertise. It is utterly
rude to let somebody else point you to the exact part of the Qt documentation
you couldn't be bothered to read.
Does this sound unfriendly? Well, maybe - but: Been there, done that, got the
fucking T-shirt -- countless times. This is not how I want to spend my spare
time.
There are some people who keep arguing that "it takes hours for me to read
through all the documentation, whereas you as an expert can give me the right
answer within a minute".
Well, yes, it might only take a minute to write the answer in IRC, but then
that newbie won't learn anything except that it pays off to disturb people
rather than learn for himself. And reading the documentation is always a good
investment of time; it is never wasted. In the process of searching for an
answer you will come across many things you hadn't known - and that might just
be useful for your next question.
Plus, it will take the expert that one or two minutes to write the answer to
IRC - and then **15-20 minutes to recover from the interrupt**, to restore the
fragile buildings in his mind he needs to solve the problem he was originally
working on.
Please keep in mind that every such interrupt will cost 20-30 minutes of time
on average, and a working day only has 16-24 such time slots; and those experts
tend to be in high demand on many different communication channels (IRC,
personal mail, mailing lists, bugzilla, phone, people walking into the office).
So, should you join the project as a newbie?
If you have patience, self-discipline and are willing to learn (which includes
reading the Qt documentation first), and, most importantly, if you are willing
to stay with the project and not let some unfortunate guy clean up half-ready
stuff, yes.
Just keep in mind that others are doing this because (a) it's fun for them
and/or (b) because they want that piece of software to be successful. Educating
newbies and cleaning up after them is very low on most developers' list of fun
things to do. They still do it, but it's painful for them. Please help
minimizing that pain.
## Further Reading
- http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
qdirstat-1.8/doc/Debugging-Tips.md 0000664 0000000 0000000 00000003200 14112476455 0017120 0 ustar 00root root 0000000 0000000 # QDirStat Debugging Tips
## Problem: Directory reading is too fast to debug anything
### Symptom
Only the very first time, reading a large directory like / takes long enough to
experiment with anything in the tree widget. Any subsequent time, it's just too
fast - one or two seconds, and *bam* it's finished already.
### Reason
The Linux kernel has become incredibly good at caching directory information,
and today's PCs have so much RAM that the kernel tends to use a large amount of
it as cache - files, inodes, dentries (directories). Once a directory is read,
it remains in the cache for a long time, so the speedup upon a subsequent read
is enormous.
### Fix / Workaround
Drop the kernel caches (as root):
su -
echo 3 > /proc/sys/vm/drop_caches
or
echo 3 | sudo tee /proc/sys/vm/drop_caches
(`sudo echo 3 > /proc/sys/vm/drop_caches` would NOT work because your non-root
shell would do the I/O redirection, so it would not have sufficient privileges)
### Reference
http://unix.stackexchange.com/questions/87908/how-do-you-empty-the-buffers-and-cache-on-a-linux-system
## Profiling QDirStat with Valgrind / KCachegrind
### Prerequesites
Install vallgrind and kcachgrind:
sudo apt install valgrind kcachegrind
### Profile
Start QDirStat with the valgrind profiler:
valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes qdirstat ~
Don't use a huge directory since the profiling slows down everyting
considerably!
The results go to a file `callgrind.out.*` in that directory. Visualize with
kcachegrind
### Reference
https://developer.mantidproject.org/ProfilingWithValgrind.html qdirstat-1.8/doc/DevHistory.md 0000664 0000000 0000000 00000430054 14112476455 0016423 0 ustar 00root root 0000000 0000000 # QDirStat Development History
This is more verbose than a traditional change log, thus the unusual name of
this file.
See the README.md file for the latest news:
https://github.com/shundhammer/qdirstat/blob/master/README.md
## QDirStat History
- 2021-08-06
- Lots of internal restructuring and refactoring to keep the code
maintainable: In particular, the MainWindow code was getting out of hand
with more and more features and menu actions being added all the time, so
some of that was moved out to separate classes.
That involved quite some testing and rethinking how certain parts are
working, which in turn involved some head-scratching, rearranging code had
the byproduct of more internal documentation and also some small bug fixes.
- The "Permissions error" panel message didn't always go away when the user
had simply left it open and just opened a new directory; and probably also
in some other situations. Now it's always cleanly removed whenever a new
directory tree is read or when it's re-read ("Refresh all" or "Refresh
Selected"). That was one of those small bug fixes.
- 2021-07-31
- Now the "File Age Statistics" window also shows statistics for the months
of this and the last year as collapsible (and by default collapsed) items
in the same list, so you can break down the age of files further for the
last 13-24 months. If a month entry is selected in that list, locating the
files of course only locates the files that were last modified within that
month.
More details and more screenshots at [GitHub issue #172](https://github.com/shundhammer/qdirstat/issues/172).
- 2021-07-29
- Added a "Back" and a "Forward" button to move back and forth in the history
of visited directories; i.e. QDirStat behaves now very much like a web
browser when navigating the filesystem.
It also has a history menu when you long-press the "Back" or "Forward"
buttons, and of course it uses the same keyboard shortcuts `[Alt] [Cursor
Left]` and `[Alt] [Cursor Right]` that all common web browsers use.
- 2021-07-28
- Added a "Locate" button to the new _File Age Statistics_ view, using the
same window as the actions from the "Discover" menu.
This is enabled if there are no more than 1000 files in the currently
selected year to avoid the results list to become too long and too
unwieldy. If there are more than 1000 files in the currently selected year,
break it down to another subdirectory first; otherwise you'd be ending up
with the better part of the whole filesystem in the results list in the
extreme case.
- 2021-07-27
- Added a whole new type of view: _File Age Statistics_, displaying file
modification times by years, so you can see during what time frame there
was any activity in a directory tree:
[
](https://user-images.githubusercontent.com/11538225/127198386-215ecc9a-325c-4954-afef-e1d7f271c013.png)
More details and a lot more screenshots at [GitHub issue #172](https://github.com/shundhammer/qdirstat/issues/172).
- 2021-07-02
- Don't show inactive (unmounted) mounts managed by the automounter anymore
in the "Mounted Filesystems" window. They were listed there as filesystem
type "autofs" and 0 bytes total size which was not very useful.
Once they become auto-mounted by a user accessing them in the filesystem,
they are shown there normally, of course.
- 2021-06-26
- Improved the fix for [GitHub issue #169](https://github.com/shundhammer/qdirstat/issues/169):
Breadcrumbs navigator becomes too wide for very long paths.
Now no longer aggressively shortening all path components in the
breadcrumbs navigator when the complete path becomes even just a little bit
too long, but concentrating on the longest parts and shortening them one by
one until the complete path is not too long anymore.
- 2021-06-24
- First (crude) fix for [GitHub issue #169](https://github.com/shundhammer/qdirstat/issues/169):
Breadcrumbs navigator becomes too wide for very long paths.
Now shortening path components if the overall path would become too wide.
Right now it shortens them a bit too aggressively.
- 2021-06-21 [QDirStat AppImage and why I don't like it](https://github.com/shundhammer/qdirstat/issues/168)
TL;DR:
- It's big and fat (113 MB)
- It's an outdated version (QDirStat 1.6.1 from 16 months ago)
- It doesn't even tell you what version it contains
- It still needs a fairly recent version of GLibc, so you can't run it on Ubuntu 18.04 LTS
- It's unclear if at least the libraries inside (e.g. the Qt libs) are up to date
------------
- 2021-04-05 **New stable release: 1.7.1**
**Summary:**
- Added a "Discover" toplevel menu with actions to easily find
- the largest files
- the newest files
- the oldest files
- files with multiple hard links
- broken symbolic links
- sparse files
- Now showing the target of symbolic links in the details panel.
If the target does not exist, a **Broken Link** warning is also shown.
- Menu reorganization. The new toplevel menus are now:
File, Edit, View, Go To, Discover, Clean up, Help
- Enabled _Refresh Selected_ now for files as well. In that case, the parent
directory is refreshed.
- Added hotkey `[F6]` for _Refresh Selected_.
- Now ignoring the loopback mounts of installed snap packages in the "Open
Directory" dialog and in the "Mounted Filesystems" window.
- Added links to external documents to a new "Problems and Solutions" submenu
of the "Help" menu so they are more easily discoverable.
- Added a document about
[finding files that are shadowed by a mount](doc/Shadowed-by-Mount.md)
and a script for the most common case.
- Bug fix: Fixed [GitHub Issue #149](https://github.com/shundhammer/qdirstat/issues/149):
Segfault when using a cleanup action with refresh policy _AssumeDeleted_
after a cleanup action with _RefreshParent_ in the same directory.
**Details:**
- Added a "Discover" toplevel menu with actions to easily find
- the largest files
- the newest files
- the oldest files
- files with multiple hard links
- broken symbolic links
- sparse files
in the whole displayed directory tree or, if a directory is selected, in
that subtree.
In each case, a non-modal dialog is opened with a list of the results.
Clicking on one of them selects it in the main window where you can see
more details and use cleanup actions.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-discover.png)
Most of that was already there in some way or the other, but now it's
easier to discover (pun intended) and to use.
Finding large files is of course what the treemap is primarily for; just
spot large blobs and click on them to find out what they are and where they
are hiding.
Finding the newest files can also be done by sorting the tree by the "last
modified" column and then opening the topmost branches. This is often
useful to find out where some browser dumped that last download.
Similarly, to find the oldest files, enable the "oldest files" tree column,
sort by that and open branches until you can see a file.
Files with multiple hard links or sparse files were mentioned in the log;
otherwise they were not so easy to find (short of using the command line,
of course).
- Now showing the target of symbolic links in the details panel.
If it's a short path, the whole path is shown; otherwise without the path
(".../somewhere"), and the full path is shown as a pop-up upon mouse click.
If the target does not exist, a **Broken Link** warning is also shown.
- Menu reorganization: They had become a little too crowded, especially on
the top level.
- The new toplevel menus are now:
File, Edit, View, Go To, Discover, Clean up, Help
I.e. it's down to 7 items which is generally regarded as the gold
standard by usability experts.
- The former "Settings" menu is gone; "Configure QDirStat" is now in the
"Edit" menu. There was only that one action in the "Settings" menu, and
that is quite wasteful in terms of screen space and toplevel menu
complexity.
- Moved out some options entirely from the menus; they are still available
when editing the config file manually:
- "Show current path"
- "Treemap as side panel"
- "Expand tree level" is now limited to level 5 (formerly 9). Opening that
many tree branches means a huge performance drop anyway.
- The former "Treemap" menu is now a submenu of "View". Most of those
actions are available as tool bar buttons and mouse wheel operations
anyway.
- Enabled _Refresh Selected_ now for files as well. In that case, the parent
directory is refreshed.
- Added hotkey `[F6]` for _Refresh Selected_.
`[F5]` is still _Refresh All_ like in all web browsers. Since window
managers / desktop environments tend to consume `[F5]` with modifier keys
(`[Shift] [F5]`, `[Alt] [F5]`, `[Ctrl] [F5]`), this is the closest we can
get, and it's more consistent than using something like `[Ctrl] [R]`.
This was inspired by the discussion in [PR#145](https://github.com/shundhammer/qdirstat/pull/145).
- Now ignoring the loopback mounts of installed snap packages in the "Open
Directory" dialog and in the "Mounted Filesystems" window.
Yes, each of them has a separate loop mount, even if it's only installed,
not in active use. Those mounts clutter the output of commands like `df` or
`mount` with nonsensical cruft:
```
df -hT | grep snap
/dev/loop0 squashfs 159M 159M 0 100% /snap/chromium/1244
/dev/loop1 squashfs 55M 55M 0 100% /snap/core18/1880
/dev/loop2 squashfs 63M 63M 0 100% /snap/gtk-common-themes/1506
/dev/loop3 squashfs 30M 30M 0 100% /snap/snapd/8542
```
(From a freshly installed Xubuntu 20.04 LTS)
- Added links to external documents to a new "Problems and Solutions" submenu
of the "Help" menu so they are more easily discoverable.
- Added a document about
[finding files that are shadowed by a mount](doc/Shadowed-by-Mount.md)
and a script for the most common case.
- Bug fix: Fixed [GitHub Issue #149](https://github.com/shundhammer/qdirstat/issues/149):
Segfault when using a cleanup action with refresh policy _AssumeDeleted_
after a cleanup action with _RefreshParent_ in the same directory.
----------
- 2021-03-24
- New document about [finding files that are shadowed by a mount](doc/Shadowed-by-Mount.md)
- New script for finding files on the root filesystem that are shadowed by a
mount (see doc link above).
- 2021-03-19
- Added a context menu to the "Locate Files" window (the "Discover" results)
with the cleanup actions that are applicable to files.
- Keyboard shortcuts for cleanups now also work in the "Locate Files" window.
- 2020-12-21
- Fixed [GitHub Issue #149](https://github.com/shundhammer/qdirstat/issues/149):
Segfault when using a cleanup action with refresh policy _AssumeDeleted_ after
a cleanup action with _RefreshParent_ in the same directory.
- 2020-11-23
- Menu reorganization: They had become a little too crowded, especially on
the top level.
- Moved out some options from the menus; they are still available when
editing the config file manually:
- "Show current path"
- "Treemap as side panel"
- "Expand tree level" is now limited to level 5 (formerly 9). Opening that
many tree branches means a huge performance drop anyway.
- The former "Treemap" menu is now a submenu of "View". Most of those
actions are available as tool bar buttons and mouse wheel operations
anyway.
- The former "Settings" menu is gone; "Configure QDirStat" is now in the
"Edit" menu. There was only that one action in the "Settings" menu, and
that is quite wasteful in terms of screen space and toplevel menu
complexity.
I experimented shortly with moving some more settings there, e.g. "Show
details panel" and "Show tremap", but I reverted that: The details panel
is different for each layout (L1, L2, L3), and the layout switching
actions are in the "View" menu where they belong; so "Show details panel"
should really remain near them. And not having "Show treemap" in the
"Treemap" submenu would be very confusing.
The new toplevel menus are now:
- File
- Edit
- View
- Go To
- Discover
- Clean up
- Help
I.e. it's down to 7 items which is generally regarded as the gold standard
by usability experts.
I am not completely happy yet with how additional views are scattered among
several menus:
- "File" -> "Show installed packages"
- "File" -> "Show unpackaged files"
- "View" -> "File size statistics"
- "View" -> "File type statistics"
- "View" -> "Show mounted filesystems"
The rationale is that those views in the "File" menu load completely new
content, replacing the scanned directory in both the tree view and the
treemap; thus they are on a similar level as "Open directory", so they are
right next to that action.
The other views open in separate windows, so they are add-on views to the
currently loaded directory tree.
- 2020-11-22
- Added a "Discover" toplevel menu to easily find
- the largest files
- the newest files
- the oldest files
- files with multiple hard links
- broken symbolic links
- sparse files
in the whole displayed directory tree or, if a directory is selected, in
that subtree.
In each case, a non-modal dialog is opened with a list of the results.
Clicking on one of them selects it in the main window where you can see
more details and use cleanup actions.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-discover.png)
Most of that was already there in some way or the other, but now it's
easier to discover (pun intended) and to use.
Finding large files is of course what the treemap is primarily for; just
spot large blobs and click on them to find out what they are and where they
are hiding.
Finding the newest files can also be done by sorting the tree by the "last
modified" column and then opening the topmost branches. This is often
useful to find out where some browser dumped that last download.
Similarly, to find the oldest files, enable the "oldest files" tree column,
sort by that and open branches until you can see a file.
Files with multiple hard links or sparse files were mentioned in the log;
otherwise they were not so easy to find (short of using the command line,
of course).
- 2020-10-23
- Now showing the target of symbolic links in the details panel.
If it's a short path, the whole path is shown; otherwise without the path
(".../somewhere"), and the full path is shown as a pop-up upon mouse click.
If the target does not exist, a **Broken Link** warning is also shown.
- 2020-10-15
- Enabled _Refresh Selected_ now for files as well. In that case, the parent
directory is refreshed.
- Added hotkey `[F6]` for _Refresh Selected_.
`[F5]` is still _Refresh All_ like in all web browsers. Since window
managers / desktop environments tend to consume `[F5]` with modifier keys
(`[Shift] [F5]`, `[Alt] [F5]`, `[Ctrl] [F5]`), this is the closest we can
get, and it's more consistent than using something like `[Ctrl] [R]`.
This was inspired by the discussion in [PR#145](https://github.com/shundhammer/qdirstat/pull/145).
- 2020-08-03
- Now ignoring the loopback mounts of installed snap packages in the "Open
Directory" dialog and in the "Mounted Filesystems" window.
Yes, each of them has a separate loop mount, even if it's only installed,
not in active use. Those mounts clutter the output of commands like `df` or
`mount` with nonsensical cruft:
```
df -hT | grep snap
/dev/loop0 squashfs 159M 159M 0 100% /snap/chromium/1244
/dev/loop1 squashfs 55M 55M 0 100% /snap/core18/1880
/dev/loop2 squashfs 63M 63M 0 100% /snap/gtk-common-themes/1506
/dev/loop3 squashfs 30M 30M 0 100% /snap/snapd/8542
```
(From a freshly installed Xubuntu 20.04 LTS)
Thanks a lot. Time to extend my `df` shell alias to exclude filesystem type
"squashfs", too:
```
alias df='/bin/df -x tmpfs -x devtmpfs -x squashfs -h $*'
```
------------
- 2020-07-26 **New stable release: 1.7**
**Summary:**
- Closing the gap between sizes reported by QDirstat and sizes reported by
the `du` command: Now also taking the allocated size into account.
- Now also displaying the allocated size where it makes sense.
- New "Mounted Filesystems" window showing output similar to the `df` command
(but without the cruft).
- New directory selection dialog showing all (real) filesystems.
- New checkbox to cross filesystems (temporarily) in the directory selection
dialog.
- Workaround for NTFS oddities: Ignoring hard links on NTFS.
- Added config option to ignore hard links in general.
- Added a document about Btrfs free size and how different tools tend to show
different values: [Btrfs-Free-Size.md](doc/Btrfs-Free-Size.md)
- Bug fixes
**Details:**
- Closing the gap between sizes reported by QDirstat and sizes reported by
the `du` command: Now also taking the allocated size into account.
There were repeated threads on various social media where users wondered
why QDirStat displayed different sizes than the `du` or the `df` commands,
sometimes slightly different, sometimes off by quite a lot.
In short, this is mostly due to the difference between a file's _byte size_
and its _allocated blocks_: On most filesystem types, a file of 49 bytes
still consumes a minimum of 4 KB (4096 bytes); disk space is allocated in
_clusters_ (typically 4 KB), not byte by byte. On a typical Linux root
filesystem with many thousands of tiny files, this difference can add up to
a lot.
Formerly, QDirStat only added up the _byte sizes_, disregarding the
allocated, but really unused part at the end of tiny files. The rationale
was that some filesystem types handle that in more intelligent ways, yet
there is no documented way to get information from a filesystem if it
actually does that. It turned out that in reality, most of them don't
bother; they simply let most of that last cluster go to waste.
Now QDirStat displays _both_ sizes where useful:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-tiny-files.png)
- For tiny files, the tree view now shows both sizes: "49 B (4k)"
- For directories, the tree view now shows the total of the _allocated_
sizes. This may sound a bit inconsistent, but it feels very natural and
intuitive: You are typically interested in how much disk space the
subtree consumes, no matter if some part of that is really wasted.
- The _details_ view shows both sizes when there is a difference (in the
displayed numeric precision): "Size: 42.1 MB" vs. "Allocated: 42.2 MB",
but not "Size: 42.0 MB" vs. "Allocated: 42.0 MB".
- Treemap tiles now correspond to a file's _allocated_ size. This makes a
real difference for tiny files.
More details at [GitHub Issue #134](https://github.com/shundhammer/qdirstat/issues/134):
_Size Difference between QDirStat Reports and the "du" and "df" Commands_.
- New "Mounted Filesystems" window ("View" -> "Show Mounted Filesystems" or
Ctrl-M):
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-filesystems-window.png)
This shows information about "normal" mounted filesystems (excluding system
mounts like `/dev`, `/proc`, `/sys`, bind mounts, Btrfs subvolumes) with
usage data as reported by the filesystem itself. The "Reserved" column
shows the disk space reserved for the root user on that filesystem, "Free"
is the available space for non-privileged users.
Sometimes the "Used" size reported here may be different from what QDirStat
reports after reading that complete filesystem; this can be due to
metadata, journals or snapshots. Notice that in those cases, the `du`
command will also display a different value than the `df` command.
- QDirStat now has its own custom directory selection dialog; it no longer
uses one of the simplistic Qt standard file dialogs:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-open-dir-dialog.png)
The "Places" bar on the left shows your home directory and all "real"
filesystems (the same as in the new "Mounted Filesystems" window). For each
filesystem, it shows
- The mount point
- The total size of the filesystem
- The filesystem type ("ext4", "btrfs", "ntfs", ...)
- The device name ("/dev/sda2") (in a tooltip)
In the "Path" combo box you can simply edit the path or copy and paste it
from another window. Use the "Up" button to move one directory level up.
- The "Cross Filesystems" checkbox lets you temporarily override the global
configuration option of the same name: QDirStat will then no longer stop
when a mount point is found during reading a subtree, it will descend into
that mounted filesystem and read it, too; but again, only for "real"
filesystems, not for system mounts such as `/dev`, `/sys`, `/proc`, not for
bind mounts, not for filesystems mounted multiple times, and not for
network mounts (NFS, Samba / CIFS).
More details at [GitHub Issue #129](https://github.com/shundhammer/qdirstat/issues/129).
- Added a workaround for wrong size sums on NTFS: Now disregarding hard links
on NTFS.
The (current?) _ntfs-3g_ implementation using _fuseblk_ seems to disagree
with Windows tools which files really have hard links.
It appears that _ntfs-3g_ regards even the MS-DOS compatible short filename
(`PROGRA~2` vs. `Program Files`) as a hard link which is of course utter
nonsense; that means that almost all files on an NTFS partition are
reported as having multiple hard links, so QDirStat displayed them as
having only half their real size.
Notice that this is a bug in _ntfs-3g_, not in QDirStat.
See also [GitHub Issue #88](https://github.com/shundhammer/qdirstat/issues/88).
-
Added a config option to ignore hard links.
This is useful for a very small number of use cases. Hard links are not
very common anymore in today's Linux / BSD / Unix-like systems, so most
users won't have to bother with this at all.
By default, QDirStat sums up the disk space for a file with multiple hard
links for each hard link's share of the overall size: If a file with 1 MB
has 4 hard links, for each of those 4 links QDirStat adds 1/4 of the size
(i.e., 256 kB) to the parent directory. If all those 4 links are in the
same directory, that's very simple: They add up to 4 * 256 kB = 1 MB, so
the sum is correct.
If those hard links are all in different directories, each directory only
gets part of that disk space allocated, because in fact they share the disk
space among each other; the total disk space sum taking all those
directories into account is still correct, of course.
The trouble starts when you want to make a backup of only one of those
directories: Even though the disk space is still shared with other
directories, on the backup medium, you still need the disk space for that
complete file, i.e. the full 1 MB, not only that directory's share (256
kB). With a lot of hard-linked files, that can add up to a lot of
difference between what QDirStat displays and what disk space you actually
need for the backup.
There was a user who makes heavy use of that, and for that kind of use case
there is now the option to ignore hard links: In that case, QDirStat sums
up the complete size (the full 1 MB) for each hard link of the file.
While that is useful for this special case, and you can now see the total
size that you will need for your backup medium for that one directory, the
total size higher up in the directory tree where more than one of those
directories that share hard linked files with each other is off: That file
now appears 4 times with 1 MB each, so it will add up to 4 MB.
There is now a new config option in `~/.config/QDirStat/QDirStat.conf`:
```ini
[DirectoryTree]
...
IgnoreHardLinks=false
```
This is intentionally not available in the GUI config dialog to avoid
confusion; use a text editor (while QDirStat is not running) to change
this setting.
Please use that config option only when you are aware of the consequences;
this is a specialized option for rare, specialized use cases. It basically
makes sense only if the other hard links are all outside the subtree that
QDirStat displays.
More details at [GitHub Issue #124](https://github.com/shundhammer/qdirstat/issues/124).
- There is now a new document about Btrfs free size and how different tools
tend to show different values: [Btrfs-Free-Size.md](doc/Btrfs-Free-Size.md)
Whenever users run out of disk space on Btrfs (which happens a lot, mostly
because of snapshots) and they try to figure out where all their disk space
went, they are confused about different tools reporting totally different
and inconsistent sizes; traditional Linux / Unix command line tools like
`du` and `df` just like GUI tools like QDirStat. Hopefully, this document
will shed some light on that.
**Bug Fixes:**
- Fixed the internal cache writer (the one called from the _File_ menu, not
the _qdirstat-cache-writer_ Perl script): For files with multiple hard
links, it wrote the wrong size to the cache file: The result of _size /
links_, not _size_.
This was part of [GitHub Issue #124](https://github.com/shundhammer/qdirstat/issues/124).
- Fixed crash when terminating with Ctrl-Q while reading directories
[(GitHub Issue #122)](https://github.com/shundhammer/qdirstat/issues/122).
- Now automatically reopening the old current branch in the tree view when
using actions like "refresh selected" and "continue reading at mount point
([GitHub Issue #135](https://github.com/shundhammer/qdirstat/issues/135)).
- Not a bug, but a minor new feature: Now automatically expanding the first
directory level of a mount point after "continue reading at mount point".
- Now correctly labelling a mount point as mount point in the "Details"
panel.
------------------
- 2020-06-14
- Now displaying the allocated size for very small files (8 kB (2 clusters)
or less) in a much more subdued way so it's still there, but less
distracting.
- If a file is wasting very much space (i.e. if it uses 33% or less of its
allocated disk space), now displaying the allocated size in bold in the
"Details" panel to draw more attention to the fact. This affects pretty
much all tiny files with 1360 bytes or less since the cluster size of most
(all?) Linux filesystem is so large (4 kB for ext4, XFS, Btrfs).
Screenshot for both changes at [GitHub Issue #134](https://github.com/shundhammer/qdirstat/issues/134).
- 2020-06-13
- Now automatically reopening the old current branch in the tree view when
using actions like "refresh selected" and "continue reading at mount point
([GitHub Issue #135](https://github.com/shundhammer/qdirstat/issues/135)).
- Now automatically expanding the first directory level of a mount point
after "continue reading at mount point".
- Now correctly labelling a mount point as mount point in the "Details"
panel.
- 2020-06-12
- NTFS is now detected as "ntfs", no longer as "fuseblk" in the "Open
Directory" and the "Filesystems" dialogs.
This was fallout of
[GitHub Issue #88](https://github.com/shundhammer/qdirstat/issues/88)
(NTFS hard links).
- Now ignoring hard links on NTFS; the (current?) ntfs-3g implementation
using fuseblk seems to disagree with Windows tools which files really have
hard links. And in this case I tend to have more faith in the Windows
tools. Now the total sizes of my Windows partitions as reported by QDirStat
are much closer to the sizes reported by the `df` command, the `statfs()`
system call and QDirStat's new "Filesystems" window.
See also [GitHub Issue #88](https://github.com/shundhammer/qdirstat/issues/88).
- 2020-06-11
- Fixed [GitHub Issue #134](https://github.com/shundhammer/qdirstat/issues/134):
_Size Difference between QDirStat Reports and the "du" and "df" Commands_:
- Now also showing the _allocated_ size in the details panel for files and
directory trees. This can make a a big difference if there are lots of tiny files.
- Now showing the _allocated_ size for directories in the tree view, not
only the sum of all the _byte_ sizes of all the files in the subtree.
- Now using the _allocated_ size in the treemap so tiny files appear with
their true size, no longer disappearing in the grey background: A 6 bytes
file is now displayed with the 4 KB that it actually consumes, not just
the 6 bytes of its content.
More information and lots of screenshots at
[GitHub Issue #134](https://github.com/shundhammer/qdirstat/issues/134).
- 2020-06-03
- New "Mounted Filesystems" window ("View" -> "Show Mounted Filesystems" or
Ctrl-M):
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-filesystems-window.png)
This shows information about "normal" mounted filesystems (excluding system
mounts like /dev, /proc, /sys, bind mounts, Btrfs subvolumes) with usage
data as reported by the filesystem itself. The "Reserved" column shows the
disk space reserved for the root user on that filesystem, "Free" is the
available space for non-privileged users.
Sometimes the "Used" size reported here may be quite different from what
QDirStat reports after reading that complete filesystem; this can be due to
metadata, journals or snapshots.
- Added a document about Btrfs free size and how different tools tend to show
different values: [Btrfs-Free-Size.md](doc/Btrfs-Free-Size.md)
- 2020-05-27
- Implemented [GitHub Issue #129](https://github.com/shundhammer/qdirstat/issues/129):
_Option to continue reading at all mount points at once_.
Previously, you could choose to either always cross filesystems while
reading directories, or you could later open the parent branch of the mount
point in the tree view and then use "Continue reading at mount point" from
the main menu / context menu.
Now you can change this setting temporarily for the current program run; it
will continue reading at "normal" mount points, i.e. excluding system
mounts like `/dev`, `/proc`, `/sys` and also bind mounts or network mounts; but
it still reads Btrfs subvolumes.
- This new option needed a check box in the "Open Directory" dialog; so from
now on, QDirStat no longer uses the generic Qt file dialog, it has a custom
one:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-open-dir-dialog.png)
In addition to that new check box at the bottom, there is now also a new
"places" widget for quick access to the user's home directory and all
("normal", see above) mounted filesystems, including network mounts (NFS,
Samba / Cifs).
- 2020-03-19
- Added a config option to ignore hard links.
This is useful for a very small number of use cases. Hard links are not
very common anymore in today's Linux / BSD / Unix-like systems, so most
users won't have to bother with this at all.
By default, QDirStat sums up the disk space for a file with multiple hard
links for each hard link's share of the overall size: If a file with 1 MB
has 4 hard links, for each of those 4 links QDirStat adds 1/4 of the size
(i.e., 256 kB) to the parent directory. If all those 4 links are in the
same directory, that's very simple: They add up to 4 * 256 kB = 1 MB, so
the sum is correct.
If those hard links are all in different directories, each directory only
gets part of that disk space allocated, because in fact they share the disk
space among each other; the total disk space sum taking all those
directories into account is still correct, of course.
The trouble starts when you want to make a backup of only one of those
directories: Even though the disk space is still shared with other
directories, on the backup medium, you still need the disk space for that
complete file, i.e. the full 1 MB, not only that directory's share (256
kB). With a lot of hard-linked files, that can add up to a lot of
difference between what QDirStat displays and what disk space you actually
need for the backup.
There was a user who makes heavy use of that, and for that kind of use case
there is now the option to ignore hard links: In that case, QDirStat sums
up the complete size (the full 1 MB) for each hard link of the file.
While that is useful for this special case, and you can now see the total
size that you will need for your backup medium for that one directory, the
total size higher up in the directory tree where more than one of those
directories that share hard linked files with each other is off: That file
now appears 4 times with 1 MB each, so it will add up to 4 MB.
So please use that config option only when you are aware of the
consequences; this is a specialized option for rare, specialized use
cases. It basically makes sense only if the other hard links are all
outside the subtree that QDirStat displays.
If in doubt, leave this option off (which is the default).
More details at [GitHub Issue #124](https://github.com/shundhammer/qdirstat/issues/124).
- 2020-03-06
- Fixed the internal cache writer (the one called from the _File_ menu, not
the _qdirstat-cache-writer_ Perl script): For files with multiple hard
links, it wrote the wrong size to the cache file: The result of _size /
links_, not _size_.
This was part of [GitHub Issue #124](https://github.com/shundhammer/qdirstat/issues/124).
- 2020-02-24
- Fixed crash when terminating with Ctrl-Q while reading directories
[(GitHub Issue #122)](https://github.com/shundhammer/qdirstat/issues/122).
--------------
- 2020-02-13 **New stable release: 1.6.1**
**Summary:**
- Much better handling for "permission denied" errors while reading directories
- Now showing the exact byte size (134 495 994 Bytes instead of 128.3 MB)
upon mouse click in the tree (right click) and in the details panel (left
or right click)
- New optional tree column "Oldest File" (not enabled by default)
- Bug fix: Support for dark widget themes in file size histogram window
**Details:**
- If you start QDirStat with insufficient permissions, you could easily
overlook large subtrees in the filesystem that consume disk space, but were
not visible to you. They did get a special icon, but you would have to open
the parent directory in the tree view to see that.
Now, QDirStat notifies you in several ways:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-err-dirs-light.png)
- All parent directories that contain a subtree that could not be read are
now displayed in dark red in the tree view.
- The _Size_ field of those directories as well as other accumulated values
(_Items_, _Files_, _Subdirs_) are now preceded with a "greater than" sign
to indicate that there is most likely more, but that information could
not be retrieved: ">7.2 MB" indicating that it's at least 7.2 MB and most
likely more than that, but we don't know because one or more
subdirectories could not be read.
- A message panel in the main window between the tree view and the treemap
with a message that some directories could not be read.
You can close the message with the `[x]` close button on its right side,
but you can also simply leave it open. This is a lot less obtrusive than
a pop-up dialog, yet less temporary than a message in the bottom status
line that will disappear in a few seconds or when anything else is
reported.
- Clicking on the "Details..." link in that message opens a separate window
to report all directories that could not be read (typically because of
insufficient permissions).
This window is non-modal, i.e. you can still interact with the main
window when it is open. Click on any directory that it lists to locate it
in the main window: The tree view will open that branch and scroll to
make it visible.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-unreadable-dirs-window.png)
- In addition to the "locked folder" icon, unreadable directories are shown
in bright red in the tree view.
- When an unreadable directory is selected in the tree view, the details
panel now shows a large padlock icon and a message "[Permission Denied]",
and the permissions are highlighted in red.
- You can now see the exact size in bytes both in the tree view and in the
details panel: 134 495 994 Bytes instead of 128.3 MB. The field is still
(somewhat) human readable with thousands separators (using blanks to avoid
confusion with different decimal / thousands separators in different
languages).
This can make it easier to compare sizes with other tools that report them
in bytes or that insist in using 1000-based units (QDirStat uses 1024-based
size units: 1 kB = 1024 Bytes; 1 MB = 1024 kB; 1 GB = 1024 MB; etc.).
Not using tool tips that appear automatically was a conscious decision:
This level of detailed information is not needed that often, and tool tips
get in the way whenever the mouse cursor lingers too long at an active
spot. More often than not a tool tip obscurs other content that the user
might want to read at that very moment. This is why in QDirStat in the rare
cases that you are interested in those exact numbers, you have to click:
- In the tree view, right-click a size field (a left click is used for
selecting an item in tree views, so the context menu is pressed into
service for that purpose (only for the size column)).
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-byte-size.png)
- In the details panel, use left or right click. To indicate what fields
can be clicked, they are now underlined when the mouse hovers over them.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-byte-size-2a.png)
_Hovering over fields that can be clicked shows them underlined, very
much like a hyperlink._
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-byte-size-2b.png)
_Clicking (left or right mouse button) shows more details: In this case,
the exact byte size._
- There is now an optional new column "Oldest File" that shows the timestamp
(the mtime) of the oldest file in a subtree. This is strictly about files;
directories, symlinks and special files (block or character devices, FIFOs
etc.) are ignored for this.
This may be useful to spot some old cruft, for example leftover dot files
in your home directory. Many programs generate such files when you start
them for the first time, and they are rarely cleaned up when they fall out
of use.
Notice that this column is not enabled by default. If you would like to use
it, switch to layout L2 or L3, right-click the tree header to open the
columns context menu, select _Hidden Columns_, then _Show Column "Oldest
File"_.
Of course you can also sort by this column to see the oldest files first
(or last).
- Fixed text color in histogram in dark widget themes
[(GitHub Issue #117)](https://github.com/shundhammer/qdirstat/issues/117).
--------------------
- 2020-02-12
- Fine-tuned error handling: If there is a "permission denied" error while
reading a directory, this will now be shown much more clearly: There is now
a clear distinction between "permission denied" any other generic "read
error".
- For directories that could not be read because of insufficient permissions,
now also showing an additional "locked" icon in the details panel, and
coloring the permissions field in red to point to the cause of the problem.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-unreadable-dirs-window.png)
This color can be configured in `~/.config/QDirStat/QDirStat.conf`:
[DetailsPanel]
DirReadErrColor=#ff0000
- 2020-02-11
- Now also showing the exact byte size of all size fields (of 1 kB and above)
upon click in the "Details" panel. All clickable fields there are now
underlined just like a hyperlink when the mouse hovers above them.
I thought long and hard about using tool tips for that, but tool tips have
a nasty habit of getting in the way and obscuring other information that
the user might want to read; so I decided to use explicit mouse clicks.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-byte-size-2a.png)
_Hovering over fields that can be clicked shows them underlined, very much
like a hyperlink._
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-byte-size-2b.png)
_Clicking (left or right mouse button) shows more details: In this case, the
exact byte size._
- 2019-12-22
- Brought back the exact byte size as the context menu for the "Size" column in the tree:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-byte-size.png)
I.e. a right click on the size now shows the exact number of bytes to avoid
confusion between those people who know what a Megabyte or Gigabyte is and
those who introduced the confusion with 1000-based units vs. the good old
1024-based units that everybody in IT uses (including Microsoft everywhere
in all versions of Windows).
_Back in the early days of computing, everything was easy: a Kilobyte was
1024 bytes, a Megabyte was 1024 Kilobytes, and Gigabytes were Science
Fiction. Then some morons came along who insisted on 1000-based units like
everywhere in Physics. And they and the Real Engineers introduced a foul
compromise: Rename 1024-based units to Kibibytes, Mibibytes etc. and
redefine Kilobytes to be 1000 bytes, Megabytes to become 1000 Kilobytes
etc.; since that day there is confusion what is what._
**QDirStat always used and always will use 1024-based units.**
- 2019-11-02
- Added a separate window to report all directories that could not be read
(typically because of insufficient permissions). This window is opened only
on request: When the user clicks on the "Details..." link in the panel
message that reports that some directories could not be read.
This window is non-modal, i.e. you can still interact with the main window
when it is open. Click on any directory that it lists to locate it in the
main window.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-unreadable-dirs-window.png)
- Directories that could not be read are now also correctly reported in the
unpackaged files view. Since they are empty when they could not be read,
they will always end up in an `` branch which was previously not
taken into account when reporting directories with read errors. This is now
fixed.
- 2019-08-24
- If directories could not be read (typically because of insufficient
permissions), now also posting a warning message in a new message panel.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-err-dirs-light.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-err-dirs-dark.png)
You can close the message with the `[x]` close button on its right side,
but you can also simply leave it open. This is a lot less obtrusive than a
pop-up dialog, yet less temporary than a message in the bottom status line
that will disappear in a few seconds or when anything else is reported.
The infrastructure for this enables multiple such messages that can be
closed in any order (or not at all) as the user likes. Each message can
have a "Details..." link (not used in these examples) to provide more
information.
- 2019-08-22
- Improved handling for directories that could not be read.
When you run QDirStat as a normal (non-root) user on system directories, it
is very common that you get a "permission denied" error for directories
that contain sensitive information. Such a directory gets a folder icon
with a little lock to indicate that it's locked for you; there is no way to
find out how much disk space it consumes.
Now, such directories are also displayed in a special color (for now bright
red) in the tree. All their parents are now displayed in another (slightly
less obtrusive) color to indicate that you probably don't see the complete
disk space information for that subdirectory.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-err-dirs-light.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-err-dirs-dark.png)
In those examples, The `/etc/ssl/private` directory does not have read
permissions for non-root users; note the icon with the lock and the red
text color.
When you don't open that branch in the tree, you might not realize this;
it's also in the log file, but most users don't read that. So its parent
directories `/etc/ssl` and `/etc` are also displayed in a different color:
Dark red in the light widget theme and yellow in the dark widget theme.
In addition to that, the parent directories now show a `>` prefix for the
size, number of items, number of files, number of subdirs fields to
indicate that there may be more. This is a hint (not only, but also) for
color blind users.
- 2019-08-12
- Toned down over-information to reduce clutter:
- No longer showing column "Oldest File" in layout L2 by default.
Of course, you can always re-enable this if you like:
Just switch to layout L2, right-click on the column header to open the
column context menu, then "Hidden Columns" -> "Show Column 'Oldest File'".
- Removed "Oldest File" from the details panel for directories:
I found that this does not contribute any useful information here, yet it
adds to the screen clutter. Information about the oldest file in a
subtree is useful to drill down deeper into the subtree to find it, so
the tree view is much better suited for that; having that information in
the details panel as well does not add any value for that procedure.
- 2019-08-03
- Fixed text color in histogram in dark widget themes
[(GitHub Issue #117)](https://github.com/shundhammer/qdirstat/issues/117).
- 2019-08-01
- Added a column "Oldest File" that shows the timestamp (the mtime) of the
oldest file in a subtree. This is strictly about files; directories,
symlinks and special files (block or character devices, FIFOs etc.) are
ignored for this.
This is the first simple approach for
[GitHub Issue #118](https://github.com/shundhammer/qdirstat/issues/118).
(Click for screenshot)
This already helped me to spot some old cruft in my home directory; some
dot directories from ancient versions of flashplayer and whatnot. This
is more helpful than I initially thought.
- Added an entry "Oldest File" that does the same in the details panel for
directories and packages.
- 2019-07-22 **New stable release: V1.6**
- Performance improvement while reading directories: On average 25% faster on
normal (non-SSD) disks
See also this article: [Linux Disk Usage Tools Compared: QDirStat
vs. K4DirStat vs. Baobab vs. Filelight vs. ncdu including
benchmarks](https://github.com/shundhammer/qdirstat/issues/97)
- Vast performance improvement for huge directories (with 100.000 entries or
more in a single directory) in the tree view: There is now instant response
for jumping from the first to the last item, dragging the scroll bar or
using the mouse wheel.
- New **packages view**:
QDirStat can now visualize the file lists of installed packages:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-pkg-details.png)
I.e. files are now grouped by the package they belong to, and in each
subtree only the files that belong to the package are displayed: In this
example, in `/usr/bin` only the `chromium-browser` binary is displayed, not
all the other files in `/usr/bin`. This is intentional.
You can display all installed packages with their file lists (but that
takes a while), or you can select just a subset. Use Menu _File_ -> _Show
Installed Packages_ or start QDirStat with a `pkg:/` command line argument.
As with the other package manager related features, this is supported for
all Linux distributions that use one of _dpkg_, _rpm_ or _pacman_ (or any
higher-level package manager based on any of those like _apt_, _zypper_
etc.).
More details at [Pkg-View.md](doc/Pkg-View.md).
- New **unpackaged files view**:
QDirStat can now visualize the files in system directories that are not
packaged, i.e. that are not part of any file list of any installed software
package.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-unpkg-usr-share-qt5.png)
This can be useful to track down problems after package upgrades or after
manually installing software with `sudo make install`.
This is supported for all Linux distributions that use _dpkg_ or _rpm_ (or
any higher-level package manager based on any of those like _apt_, _zypper_
etc.).
More details at [Unpkg-View.md](doc/Unpkg-View.md).
- New standard cleanup: _Check File Type_. This uses the `file` command to
find out more detailed information what exactly a file is and displays it
in the cleanup output window.
More details, screenshots and how to get it if you already have an existing
QDirStat cleanup configuration file (i.e. if you used QDirStat before):
[GitHub Issue #102](https://github.com/shundhammer/qdirstat/issues/102).
- Implemented [GitHub Issue #90](https://github.com/shundhammer/qdirstat/issues/90):
Support excluding directories containing a file with a specific name or pattern.
Similar to some backup tools, you can now specify an exclude rule that lets
you exclude a directory that contains a file like `.nobackup` or
`.qdirstatexclude`.
- Greatly improved the man page; see `man 1 qdirstat`.
- Some bug fixes.
See also the [release announcement](https://github.com/shundhammer/qdirstat/releases/tag/1.6).
--------------------------------------------------
- 2019-07-18
- Greatly improved the man page; see `man 1 qdirstat`.
It started with the Debian maintainer of QDirStat asking for a man page
because that's a standard requirement for Debian packages, and he even
wrote the initial one; thanks again, Patrick!.
That initial man page was very concise, and as QDirStat keeps evolving, not
only was there an increasing number of command line options that was not
documented in the man page (but of course when invoking the program with
the `--help` command line option), but it also didn't explain much beyond
the command line arguments.
Now it contains not only the latest set of command line arguments including
syntax and meaning of `pkg:/` and `unpkg:/` URLs, but also some general
information what the program is (including what the treemap is) and how to
use it.
- 2019-07-08
New **unpackaged files view**:
QDirStat can now visualize the files in system directories that are not
packaged, i.e. that are not part of any file list of any installed software
package.
This reads the complete file lists first (i.e. all file lists from all
installed packages), then reads the requested directory as usual and puts the
files that are packaged in a special branch `` in the tree view.
Those files are _not_ displayed in the treemap, i.e. the treemap now only
contains unpackaged files.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-unpkg-usr-share-qt5.png)
**What is this Good For?**
- Recovering a wrecked system after botched upgrades
- Recovering from too much `sudo make install`
- Fixing packaging problems, e.g. find leftover shared libs that tend to get in
the way
- QA for distro release managers, QA engineers, PMs
- Satisfying user curiosity
- _Because we can!_ ;-)
More details at [Unpkg-View.md](doc/Unpkg-View.md).
Comments and questions are welcome at [GitHub Issue #110](https://github.com/shundhammer/qdirstat/issues/110).
If you have a genuine problem with the new feature, please open a separate
issue so it can be tracked properly.
- 2019-06-16
- Added [documentation for the _pkg-tools_ scripts](scripts/pkg-tools/README.md).
In short, they can be used to see unpackaged files on a system that uses
one of the supported package managers (_dpkg_, _rpm_, _pacman_), but it's a
bit of a clunky solution, so this is meant for advanced users only.
~~With a little bit of luck, there _may_ be a better solution forthcoming
with real integration into QDirStat's GUI.~~
_Update 2019-07-08: This real integration into the GUI is now available._
- 2019-05-12
- New standard cleanup: _Check File Type_. This uses the `file` command to
find out more detailed information what exactly a file is and displays it
in the normal cleanup output window (the orange text is the interesting
part).
More details and screenshots at [GitHub Issue #102](https://github.com/shundhammer/qdirstat/issues/102).
Notice that you can also add this to any older version of QDirStat.
- 2019-05-11
- Implemented the single-command call to get all file lists for all installed
packages for _rpm_ as well.
Now it's only _pacman_ that still needs a separate external command for
each package. If anybody knows how to do this for _pacman_ as well, please
let me know.
- Another drastic performance improvement in the packages view:
Now down to **6.5 seconds** on my system from initially 180 seconds for
getting all file lists for all 2400 installed packages.
| sec | Version | Description |
|------:|------------|---------------------------------------------------------------------|
| 180.0 | ce3e793298 | First pkg view; sequential separate `dpkg -L` calls |
| 53.4 | 68038f0525 | Separate `dpkg -L` calls in multiple background processes |
| 38.5 | ce54879a48 | Single `dpkg -S "*"` call to get all file lists for all pkg at once |
| 37.7 | 45b0a7a941 | Use cache for `lstat()` syscalls |
| 24.6 | c50e9a7686 | Use slower update timer for tree view while reading |
| 6.5 | a1043a20fb | Keep tree collapsed during reading |
(Much) more details at [GitHub Issue #101](https://github.com/shundhammer/qdirstat/issues/101).
- 2019-05-10
Drastic performance improvements in the packages view:
- When reading many (configurable; right now 200) package lists, QDirStat no
longer fires off a separate background process (6 in parallel at any given
time) for each external command (`dpkg-query --listfiles` or `rpm -ql` or
`pacman -Qlp`) and collects their output.
Rather, it now tries to use a single external command that can return all
file lists for all packages at once. It builds a cache from that and uses
it to build the internal tree as it processes the read jobs for each
package one by one.
Right now this works for _dpkg_ (`dpkg -S "*"`). Experiments show that it
will also work for _rpm_ (that's on the _to do_ list).
But there does not seem to be an equivalent command for _pacman_; it looks
as if _pacman_ can only return a file list for a single package or a list
of all installed packages, but without any reference what package each file
in that list belongs to. _If anybody knows, please contact me._
- Now caching the result of `lstat()` syscalls for directories in the package
view since most packages share common system directories like `/usr`,
`/usr/bin`, `/usr/share` etc.; `lstat()` is an expensive affair, and even
just avoiding to switch from user space to kernel space and back that often
is a speed improvement.
- Reduced the display update inverval in the packages view. While reading
package information, there is not all that much to see anyway. Yet
constantly recalculating the column widths to make sure they fit their
content is expensive. This is now done just every 5 seconds, not 3 times a
second.
There is even a noticeable difference when using the L1 layout and a
smaller window size so there is less content to take care of.
The net effect of all this performance tuning is that on my machine (Xubuntu
18.04 LTS (i.e. _dpkg_) with ~2400 packages) reading all packages with all
their file lists is now down to under 30 seconds from formerly 90 to 120 (it
varied wildly).
- 2019-05-09
- Now no longer showing a directory's own size (the size of the directory
node, not of any file contained in the directory) in the packages view:
This distorted both the treemap and the total sums. Directories are
typically shared between a lot of packages, so it does not make very much
sense to add the size of a very common directory like /usr/bin or /usr/lib
to the total size of each package that owns a file in any of them, thus
accounting for those directories many times. On my system, /usr/bin is
shared between 454 packages, so its 68 kB would be added up 454 times, thus
adding up to 30 MB.
In the treemap that meant that packages that install only one or two very
small files (symlinks!) to a very common directory would show a lot of
empty space; the 56 byte (or so) symlink would be completely dwarfed by the
directory it is in, even if the directory only has 4 kB. A lot of such lone
small files each in a separate directory meant a whole lot of empty space
in the treemap, thus making packages very hard to compare against each
other.
Of course this means that the size of the directory nodes is now completely
missing in the toplevel total sum (the Pkg:/ node in the tree), but that is
much less distorting than multiplying each of those directory node sizes by
the number of packages that have files in each of them.
- No longer regarding the directory's own mtime (modification time) in the
packages view: The latest overall mtime in a subtree cascades upward, so
any change in any subtree would affect the latest mtime in the higher tree
levels. But if that change was caused by something outside of the current
view, this is irrelevant. So if you want to know the latest mtime anywhere
in package _foo_ which includes the /usr/bin/foo command, it is irrelevant
if one hour ago you installed or updated some other package which also
installed some other commands to /usr/bin; you don't want that latest mtime
of the /usr/bin directory to affect the display of every package that has a
file in /usr/bin.
- 2019-05-04
New **packages view**:
QDirStat can now visualize the file lists of installed packages:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-pkg-details.png)
I.e. files are now grouped by the package they belong to, and in each subtree
only the files that belong to the package are displayed: In this example, in
`/usr/bin` only the `chromium-browser` binary is displayed, not all the other
files in `/usr/bin`. This is intentional.
You can display all installed packages with their file lists (but that takes
a while), or you can select just a subset. Use Menu _File_ -> _Show Installed
Packages_ or start QDirStat with a `pkg:/` command line argument.
As with the other package manager related features, this is supported for all
Linux distributions that use one of _dpkg_, _rpm_ or _pacman_ (or any
higher-level package manager based on any of those like _apt_, _zypper_ etc.).
More details at [Pkg-View.md](doc/Pkg-View.md).
Comments and questions are welcome at [GitHub Issue #100](https://github.com/shundhammer/qdirstat/issues/100).
If you have a genuine problem with the new feature, please open a separate
issue so it can be tracked properly.
- 2019-04-12
- **Performance improvement** while reading directories: **25% faster** on my
/work directory with an ext4 filesystem with 230 GB / 216k items on a
rotational (non-SSD) disk; with cleared caches now 24.5 sec average
compared to previously 32.5 sec average (with filled caches down to 1.5
from previously 2.0 sec).
It now uses `fstatat()` (instead of `lstat()`) which accepts the file
descriptor of an open directory, so glibc and the kernel save the time
previously needed for parsing the path and locating the directory; that
part will also bring some speed improvement for SSDs.
In addition to that, the entries for each directory are now sorted by i-no
before calling `fstatat()` so the kernel can now read the i-nodes on disk
in sequential order, thus saving disk seek times. SSD users will not
benefit from that since there are no disk seek times on an SSD.
- Now using the name as the secondary sort field in the tree view if the
primary sort field (usually the size) is equal for two items.
- Vast performance improvement for huge directories (with 100.000 entries or
more in a single directory) in the tree view: There is now instant response
for jumping from the first to the last item, dragging the scroll bar or
using the mouse wheel.
It had turned out that by default the underlying QTreeView widget queries
each item in turn how tall it wants to become (using the `sizeHint()`)
which in turn had to query the font for each one for its metrics.
QDirStat now sets the QTreeView's `uniformRowHeights` flag to indicate that
all rows have the same height, so this only needs to be done for the first
one, and the result is simply multiplied by the number of items.
Amazingly enough it was not sorting the items (which is what comes to mind
when there is such a performance bottleneck), no, it was someting as
mundane as the widget having to figure out the proportions of its scroll
bar slider vs. the scroll bar overall length. And for that, it needs to
know the number of items (which is simple) and the height of each one
(which was not).
The reason why the widget does that is because each item might have a
different font or a different icon, and then each item might have a
different height. That `uniformRowHeights` flag tells it that this is not
the case.
- 2019-04-06
- New article _Linux Disk Usage Tools Compared: QDirStat vs. K4DirStat
vs. Baobab vs. Filelight vs. ncdu_ including benchmarks:
[GitHub Issue #97](https://github.com/shundhammer/qdirstat/issues/97)
(written in the GitHub issue tracker so users can join the discussion)
- 2019-04-05
- Performance boost for huge directories (with 100.000 entries or more in a single
directory):
A routine that counts the direct children of a directory now uses a cached
value for each directory so it does not have to be recalculated over and
over again even if nothing changed. Amazingly enough, this little thing had
turned out to be the performance bottleneck that had made QDirStat
prohibitively slow for such directories. It was not the sorting of the
entries (the sort order was always cached), no, the problem was something
as trivial as counting the children on the current level of the tree view.
Of course, a directory that contains 100.000 entries in a single level
still has quite some performance impact, but at least now it's
tolerable. This was tested with up to 500.000 entries in a single directory
(there is now a script that can create such a directory in the test/util
directory of the source tree).
Hint: Avoid dragging the vertical scroll bar of the tree view in such a
directory; better use keyboard commands such as the _Home_ or the _End_
key. The scroll bar will make the underlying Qt widget go through every
single entry in turn, and that will take a while (it will eventually become
responsive again, though).
_Update 2019-04-12: This is now no longer an issue; using
`uniformRowHeights` fixed that._
- Implemented [GitHub Issue #90](https://github.com/shundhammer/qdirstat/issues/90):
Support excluding directories containing a file with a specific name or pattern.
Similar to some backup tools, you can now specify an exclude rule that lets
you exclude a directory that contains a file like `.nobackup` or
`.qdirstatexclude`. The exclude rule configuration now has a new option for
that:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-config-exclude.png)
This makes it possible to reuse such files that are there anyway for some
other tool and get a good idea how large the resulting backup will become.
Since this change required some refactoring in a quite sensitive part
(reading the directories), please watch out for possible bugs that this might
have introduced and report it if you find something.
--------
- 2018-11-07 **New stable release: V1.5**
Summary:
- (Optional) breadcrumbs navigation
- (Optional) a new "details" panel for the currently selected item
- (Optional) new tree columns:
owner, group, permissions both in "rwxrwxrwx" and in octal format
- Package manager support for the major Linux package managers (dpkg / rpm /
pacman) to see what package a system file belongs to.
- Quick-switchable different layouts for the main window
- A new "General" page in the configuration dialog
- Show in the window title if the program runs with root permissions (`sudo`
etc.)
- (Optional) show the URL in the window title
- Some bug fixes
For more details, see the [full release announcement](https://github.com/shundhammer/qdirstat/releases/tag/1.5).
- 2018-11-03
Added showing release notes (in an external web browser) to the "Help" menu
("What's New in this Release").
- 2018-10-26
The pre-1.5 Beta is out: [QDirStat-1.4.97-Beta](https://github.com/shundhammer/qdirstat/releases/tag/1.4.97-Beta)
- 2018-10-21
- Updated all screenshots to the latest Git source version in preparation for the
upcoming pre-1.5 Beta.
- Added a little left margin to the "Latest MTime" column in the tree to make
it look less overcrowded.
- 2018-10-20
- Reintroduced showing the elapsed time during directory reading.
You might have noticed that QDirStat's performance has decreased with all
the kernel patches to work around the Meltdown and Spectre security
problems caused by CPU design; system calls have become a lot more
expensive in terms of performance now. And QDirStat does a LOT of system
calls while reading directories: `opendir()` / `readdir()` for each
directory in the tree and `lstat()` for every single file or directory
found in the tree: My 6.8 GB root filesystem has 275,000 items total and
25,500 directories which means well over 300,000 system calls. Every single
one of them now causes kernel page tables to be cleared and restored for
every switch between user space and kernel space, and that means quite some
performance impact.
This all means that it's now worthwhile again to display the elapsed time
during directory reading. It used to be over in a heartbeat, so it wasn't
worthwhile to display that; but that's different now.
- Added a _General_ page to the configuration dialog for miscellaneous
settings.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-config-general.png)
This is a bit unorganized (as might be expected for misc settings), but
those misc settings had accumulated over time, so I decided to finally add
such a page.
The settings were always accessible, but only by editing the config file
(`~/.config/QDirStat/QDirStat.conf`) manually. For some settings you might
still have to do that: Some are too exotic for general use, some others
would confuse the average user much more than they would help.
- 2018-10-19
- Added different layouts to the main window:
You can now switch between three (at the moment) different layout options
for the upper half of QDirStat's main window.
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-file-L1.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-file-L2.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-file-L3.png)
- Layout 1 (short): Display only a bare minimum of columns in the tree
view, but show the new details panel on the right side. This is to
minimize clutter in the tree view, yet keep all the information
available.
- Layout 2 (classic): Display the same columns as always in the tree view
and additionally the new details panel on the right side.
- Layout 3 (full): Display all available columns in the tree view,
including the new file owner, group, permissions in both "rwxrwxrwx" and
octal. But don't display the new display side panel so there is enough
screen space to show all those columns.
Switching between the layouts is as easy as pressing one of the three new
buttons in the tool bar: L1, L2, L3. Or use the corresponding entries in
the "View" menu. Or use the Alt-1, Alt-2, Alt-3 key combinations.
For each view, you can individually configure what columns to display and
whether or not to display the new details side panel and / or the new
breadcrumbs navigator.
The column widths are still configured globally (and this will remain like
that); I experimented with that and found it _very_ awkward to have to set
all of them individually for each layout.
- We are approaching a new release (I guess you figured that with all the
recent changes). Most likely there will be at least one Beta release (if
there are problems maybe more) before the 1.5-stable release.
- There is still some (limited) time to add even more package managers if
anybody feels inclined to submit patches. But please be advised that I
can't do much maintenance for any of those since I don't have any system
with them readily available to test anything; the ones that I have use
_dpkg_ or _rpm_.
- Fixed [GitHub Issue #86](https://github.com/shundhammer/qdirstat/issues/86):
CacheWriter errors go unnoticed much too easily.
This was a direct result of me giving in to nagging people wanting features
of very limited value: The status bar flickering like crazy all the time
because somebody back some time ago had wanted the current treemap tile's
path and size in the status bar as the mouse hovers over it.
[GitHub Issue #30](https://github.com/shundhammer/qdirstat/issues/30)
The effect is that nobody pays attention anymore at all to that status bar
because it's flickering all the time anyway, so it has become useless as a
tool to report anything of importance; and status bar messages are gone
immediately, too, when the user happens to move the mouse across the
treemap.
As a consequence, I just disabled that by default; if anybody really wants
it, edit the QDirStat config file (`~/.config/QDirStat/QDirStat.conf`) and
enable it again:
UseTreemapHover=true
_Update 2018-10-20: This can now be changed in the new "General" page of
the configuration dialog; no need to edit the config file manually._
- 2018-10-18
- Added support for the _pacman_ package manager for Manjaro and Arch Linux.
This should now cover the most common package managers for Linux to find
out what package a system file belongs to: _dpkg_, _rpm_, _pacman_.
As mentioned before, higher-level package managers such as _apt_, _zypper_,
_yum_ or front-ends like _synaptic_, _PackageKit_ all use one of the
lower-level package managers internally, so it doesn't matter if you never
used one of the lower-level tools before.
- Tried to add support for the _pkg_ package manager ("pkg info") for FreeBSD
/ OpenBSD, but unfortunately it only knows what package owns files of
_ports_ / _3rd party_, not for the base system.
The helpful people in the _#freebsd_ IRC channel on _freenode_ confirmed
that. So this will have to wait until there is useful support for it from
the system side on those platforms. _BSD people, let me know!_
- 2018-10-16
- QDirStat now shows `[root]` in the window title if it is running with root
privileges.
- If invoked with `sudo`, now restoring the owner of the config files to the
real user (if possible) if those file are in the user's home directory.
Previously on some systems they were owned by _root_ which meant they were
no longer writable by the real user, silently discarding all subsequent
changes to the configuration (including window sizes etc).
This might be different depending on how `sudo` is configured on a system;
on SUSE, it uses the root user's home directory, on Ubuntu, the home
directory of the user who invoked `sudo`.
- 2018-10-07
Added better classification of files to the new file details view:
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-file-L2.png)
- MIME Category - this is the same as in the treemap colors, the same as you
can configure in the _MIME Categories_ page in the QDirStat configuration
dialog. By default, it shows very broad categories ("Documents, "Music",
"Images", "Videos", "Source Files", ...), but you can configure them to
much finer detail if you wish.
- System file or not. This is important if you want to run any cleanup
actions in that directory; you probably don't want to mess with system
files, even if running QDirStat as root.
A system file in this context is a file that is either owned by a system
user (a UID < 500) or that is located in a known system directory (/usr,
/lib, ..., but not /usr/local).
- For system files, the package that this file belongs to. This gives a
surprising amount of insight (it was surprising to me, at least) where all
the disk space on the system directories goes to, most importantly some of
the big blobs in the tremap.
As of now, this is supported for Linux systems using a package manager
based on _dpkg_ or on _rpm_:
- Debian
- Ubuntu / Kubuntu / Xubuntu / Lubuntu
- SUSE (openSUSE Tumbleweed or Leap, SLES)
- Red Hat (Fedora, RHEL)
... and dozens more (basically all that are based on any of the above).
This works by running `dpkg -S` or `rpm -qf` as external commands, so this
is a somewhat expensive operation. To keep the user interface responsive,
QDirStat now has an "adaptive timer" for updating that information:
Normally, the result is shown instantly, but if you click around wildly,
there is a timer that is increased or decreased (thus "adaptive") for a
delayed update after that timeout (0 / 333 / 1000 / 2500 millisec right
now).
It can even handle _rpm_ installed as a foreign package manager on a _dpkg_
based system (and the other way round); it tries the primary package
manager first, then any others that are also installed.
Please notice that _apt_, _synaptic_, _zypper_, _pkgkit_ and whatnot are
all higher level package managers that ultimately use one of the low level
ones, so even if you only use a higher level package manager, it still
works without restriction.
If your system does not use _dpkg_ or _rpm_, those who can are invited to
contribute patches for other package managers; it's really simple:
https://github.com/shundhammer/qdirstat/blob/master/src/PkgManager.cpp#L140
The API is not final yet; there may be more regexp support in the near
future (so it will only get simpler). But you get the idea.
--------------------------------------------------
- 2018-10-03
- Added a new details view next to the tree view.
Of course this can be disabled (Menu _View_ -> uncheck _Show Details Panel_).
This view shows context-sensitive information about the currently selected
item(s); see also the screenshots (still not complete, but you get the idea):
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-file-L2.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-dir.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-dot-entry.png)
[
](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-details-multi-sel.png)
What that details view displays so far:
- File: name, type (file / symlink / block device / character device /
FIFO), size, user, group, permissions both as rwxrwxrwx and octal,
modification time.
- Directory: name with appended slash to easier recognize what it is, type
(directory), subtree total size, total items, total files, total
subdirs, latest modification time in the entire subtree; directory own
size, user, group, permissions both as rwxrwxrwx and octal, modification
time of the directory node itself (that was never shown before).
- pseudo directory: Only the subtree information like for a
directory, but no user / group / permissions since there is no
counterpart for it on the filesystem.
- Multi-selection: Number of selected items, total size, number of files,
number of directories, number of files in any subtrees of those
directories. This should show a bit more clearly what is affected if you
choose to delete all that selected stuff.
The view can scroll, so extremely long file names (as are common e.g. below
`.git/objects` directories don't blow this view up to take all the screen
space away from the tree and the treemap.
- Unified the different size columns into one: No more "Subtree Size" and
"Own Size" separately, but now just "Size". The reasoning used to be that
there was no way to tell how large the directory node itself was. But that
information is now readily available in the details view if anybody is
really interested.
Plans for the immediate future:
- Add some package manager support, at least for the very common ones on
Linux (_deb_ and _rpm_ so far): Find out what package a system file belongs
to and show it (on demand or after a short delay) in the details view. This
can be done even as non-root with some commands like `dpkg -S` or `rpm
-qf`. There will probably be support for adding your own command lines in
the config file if you use another package manager.
- Some simple checks if a file is probably a system file; for example, files
below `/usr/bin` (and other very common system directories) and/or files
that are owned by a user with a UID < 500 (or so) are very likely system
files that should be very careful to delete. The details view should show
you that; maybe there should also be a warning in the cleanup actions if
any such files are affected by a potentially destructive cleanup action.
- Easily switchable different layouts for the tree columns and the details
view:
- Minimalistic: Only the bare essentials of columns plus the details view.
This should remove a lot of the current clutter on the screen, and it
should display the same information, only rearranged a bit. How often do
you really need fields like number of items / files / subdirs in the tree
view? They would be most useful there if you wish to sort the tree after
any of them. How often do you do that? And with the new details view, the
information is still available, but does not clutter the table.
- Default: Pretty much what you can see now in the new screenshots
- Maximum information: All columns, including the new user / group /
permissions columns, but (to make space) no details view
If it makes sense (not sure yet), maybe also user defined views (say, 3 of
them?) that you can define to your personal liking. I kinda like how camera
makers use that (U1 / U2 on Nikon cameras, C1 / C2 / C3 on Canon and
Panasonic). I am not completely sure yet just how useful that is; I'll need
to experiment.
- 2018-10-02 Implemented a _breadcrumbs_ widget to show the current path and
for easier navigation up the directory hierarchy. See also the new
screenshots.
Of course this can be disabled (Menu _View_ -> uncheck _Show Current Path_).
- 2018-09-27 Fixed [GitHub issue #84](https://github.com/shundhammer/qdirstat/issues/84):
Crash if picking up a cache file in the starting directory (subtree root).
This was a crash that happened when users had used the supplied
_qdirstat-cache-writer_ script to generate cache files in certain directories
for faster directory scanning (at the price of having slightly outdated
data), and QDirStat was not started with that cache file as a command line
argument, but it would find it while reading the directory at the starting
directory (and only there). This was probably broken for a long time, yet
nobody had noticed (or nobody bothered to write a bug report). This might be
an indication that this cache file feature is not widely used, so only a
small number of users seem to be affected. Anyway, this is now fixed.
- 2018-09-23 Implemented [GitHub issue #80](https://github.com/shundhammer/qdirstat/issues/80):
Show directory/file user (owner), group and permissions in the tree view.
Those new columns are not visible by default. Use the context menu in the
tree columns header to enable them. They might be useful for some users; for
others, they may be just more clutter being displayed.
Sorting by those colums is somewhat basic; both user and group are sorted by
the numeric uid or guid; the permissions are sorted by the numeric value of
the mode field. Looking up user or group names is a somewhat costly
operation. It might also make sense to order system files first (user with
UID 0, i.e. root; other system users also have small UIDs.)
See issue #80 for a screenshot.
- 2018-08-26 Noah Davis (noahdvs) contributed a new application icon for QDirStat:
I had made the old icon myself back in early 2000 for the first KDirStat 0.86
release. I never liked it very much, but the new application just needed an
icon. Finally somebody with more artistic talent than myself made one that
looks a lot more professional. Thank you, Noah!
- 2018-04-26 Implemented [GitHub issue #77](https://github.com/shundhammer/qdirstat/issues/77):
Show the current URL in the window title. This is disabled by default.
You can enable it manually in the config file (`~/.config/QDirStat/QDirStat.conf`):
[MainWindow]
...
UrlInWindowTitle=true
Some day this will be configurable in a new tab in the configuration dialog,
but right now there are only so few options that would go to such a "General"
or "Misc" tab that it would look pretty lost and unorganized.
- 2018-02-08 Fixed [GitHub issue #74](https://github.com/shundhammer/qdirstat/issues/74):
Crash deleting folder while scan is in progress
This fix comes on two levels:
- A fix on the GUI-level that simply makes sure that the "move to trash"
action in the tool bar / context menu is disabled while a directory tree is
read.
- A fix on the low-level internal classes for the in-memory directory tree
and the read job queue: This now also makes sure that whenever a subtree is
deleted from the outside (e.g. because of cleanup actions), any pending
directory read jobs for that subtree are removed from the job queue.
- 2018-02-03 Fixed [GitHub issue #72](https://github.com/shundhammer/qdirstat/issues/72):
Allow to specify install prefix
You can now install to another location like `/usr/local` if desired.
The default remains `/usr`. See section _Install to a Custom Directory_.
- 2018-01-12 Some small fixes:
- Fixed duplicate keyboard shortcut for actions "Stop Reading" (now: Ctrl-S)
and "Copy URL to Clipboard" (still Ctrl-C).
- Fixed exclude rules not matching correctly against direct root directory
children: A rule that should match "/var" now works correctly. You'd need
to specify "//var" in the rule which of course was wrong.
- Now only adding the default exclude rule ".snapshot" once. If you remove
that one, it should no longer keep reappearing if there are no other
exclude rules.
- Fixed some minor issues in the exclude rule configuration dialog with some
widgets not being correctly disabled if they made no sense to use.
----------------------------
- 2017-06-04 **New stable release: V1.4**
It's about time to ship all those latest changes.
- 2017-06-04 Fixed problem with directories that have read, but not execute
permissions thanks to _slodki_:
In that case, you'd get a warning in the log for every entry in such a
directory, and it would get the wrong icon (a locked folder) and null values
for all fields. Now checking for execute and read permission of the directory
in advance and not even trying to read any contents (because the values would
be bogus anyway).
- 2017-05-31 Fixed [GitHub Issue #61](https://github.com/shundhammer/qdirstat/issues/61):
Files and directories with UTF-8 special characters in the name not read
correctly when built with Qt 4.x
This happened only when QDirStat was built against Qt 4.x, but that is the
default for NHellFire's PPA, so this affects all Ubuntu users who installed
QDirStat from that PPA.
Thanks to _slodki_ who pointed this problem out!
- 2017-05-12 Checked code with [Coverity](https://scan.coverity.com/)
Coverity offers free static code analysis for Open Source projects.
This is really an outstanding tool, and it does a really thorough analysis.
You might be glad to hear that while it complained about some minor things,
there was not a single issue that would have been user relevant (let alone
any security problems - there were none). Still, I did my best to fix the
small complaints it had, and now we are down to zero outstanding defects
reported by Coverity in QDirStat's 130,000 lines of code.
- 2017-04-21 More consistency between file type and size statistics
Like the new file size statistics window, the older file type statistics
window now uses the currently selected directory (in the tree view), not
always the tree's toplevel directory. If nothing is selected, it still uses
the toplevel directory.
That means that F3 no longer toggles that window, but re-populates it with
the currently selected directory instead. This is consistent with the F2
view.
Of course, the "Locate Files by Type" window now is also restricted to that
subtree which actually gives it better functionality if you know that you
want to locate files only there.
This means that you can now select a subdirectory in the tree, open the file
type statistics for it (F3 key), then select any filename extension (suffix)
in that window and then open the file size statistics (F2 key) for that file
type in that subtree.
Previously, you would have to start QDirStat to show only that directory,
then open the file type statistics window (F3), then the file size statistics
window (F2) from there.
- 2017-04-14 _Let's do some real statistics_
It's been a while since the last official news here, but I wasn't idle during
that time:

This is a whole new kind of statistics in QDirStat showing how file sizes are
distributed. You can start that for any selected directory (menu _View_ ->
_File Size Statistics_ or F2) or from the _File Type Statistics" window if
you select any filename suffix (extension) there and then _File Type_ ->
_Size Statistics_ (or F2). In the latter case, you can see how large all your
photos (.jpg), your videos (.mp4) or whatever are.
This new statistics window deals with a lot of things you might have come to
hate at school or at university, and which your math teacher or your
statistics professor never explained in a way that mere mortals can
understand, so I added those explanations as a bonus. There is a landing page
for that in that new window:

Or you might use
[this](https://github.com/shundhammer/qdirstat/tree/master/doc/stats)
as a starting point.
Everybody thinking "I have no clue what this is all about", please have a
look at the
[Median, Quartiles and Percentiles Explained](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md)
document to convince yourself that really **everybody** can easily understand
this.
I also opened a
[GitHub issue to discuss this](https://github.com/shundhammer/qdirstat/issues/60);
comments are welcome.
- 2017-03-10 Filling the gaps in the treemap
[GitHub issue #58](https://github.com/shundhammer/qdirstat/issues/58) shows
that users feel under-informed when there are grey areas in the treemap. The
explanation is simple: Treemap tiles are only displayed when they have at
least a certain minimum size (by default 3 pixels). Otherwise the treemap
just gets cluttered with tiny things that don't show any information
whatsoever.
The remaining space is taken by its parent directory's tile. They were
rendered just flat grey which makes their boundaries against each other
invisible, thus giving the impression that there is nothing.
So I experimented with visible borders, but that completely destroyed the
visual impression of the treemap because those borders were everywhere. Fill
patterns also didn't help: They were just ugly, and there was no way to tell
where one directory tile ends and where the next one starts.
Then I tried gradients. The first impression was good, but then I found that
it was hard to tell which item was a (now over-emphasized) directory and
which one a large file. Locating large files deep inside the directory
hierarchy is the major strong point of the treemap visualization, so I
wouldn't want to give that up. After playing a bit with the gradient
parameters (toning it down and giving it just a little blueish tint) I ended
up with this:

I think this is a good compromise.
Of course this is configurable: Edit `~/.config/QDirStat/QDirStat.conf`:
[Treemaps]
...
DirGradientEnd=#707080
DirGradientStart=#606070
...
UseDirGradient=true
Beware that QSettings sorts the entries alphabetically, so the start is after
the end (how philosophical...).
----------------------------
- 2017-03-05 **New stable release: V1.3**
- 2017-02-27 Implemented [GitHub issue #30](https://github.com/shundhammer/qdirstat/issues/30):
When hovering over a treemap tile, display the full path and the total size
of that element in the status bar. When the hover ends (when the mouse cursor
leaves the treemap tile), display the current selection again in the status
bar.
- 2017-02-24 Improved logging: More secure and automatically log-rotating.
QDirStat now uses its own log directory `/tmp/qdirstat-$USER` (where `$USER`
is your user name; the numeric user ID is now only used if the user name
cannot be obtained). It no longer keeps one single log file growing, but
starts a new one each time it is started. 3 old logs are kept; any older ones
are deleted.
The permissions for that directory are set up in a pretty restrictive way
(0700, i.e. `rwx------`) when it is created. If it already exists, QDirStat
checks the owner and creates a new one with a random name if it is owned by
anyone else than the user who started QDirStat.
[sh @ balrog] ~ 68 % ls -ld /tmp/qdirstat-sh
drwx------ 2 sh sh 4096 Feb 24 18:29 /tmp/qdirstat-sh
[sh @ balrog] ~ 69 % ls -l /tmp/qdirstat-sh
total 16
-rw-rw-r-- 1 sh sh 2067 Feb 24 18:29 qdirstat-00.old
-rw-rw-r-- 1 sh sh 2067 Feb 24 18:07 qdirstat-01.old
-rw-rw-r-- 1 sh sh 2067 Feb 24 18:07 qdirstat-02.old
-rw-rw-r-- 1 sh sh 2067 Feb 24 18:29 qdirstat.log
For anybody regularly watching the log file this means they will now have to
use `tail -F qdirstat.log` rather than `tail -f` since the latter does not
realize when the file it watches is renamed and a new one is created under
the same name.
- 2017-02-23 Fixed [GitHub issue #24](https://github.com/shundhammer/qdirstat/issues/24):
During directory reading, subdirectories would get out of sync when opening
a tree branch.
It looks like QDirStat's tree display was a bit too dynamic for the concepts
of the underlying Qt classes (QTreeView / QAbstractItemModel): During
reading, QDirStat would sort the tree by the number of pending read
jobs. That number is constantly changing, so the sort order would also
constantly need to change. This is very hard to do properly with the
limitations those underlying classes impose; basically it would require a
reset of all the data the QTreeView keeps, thus making it forget things like
its current scrollbar position or which tree branches were expanded or
collapsed. That would make the user interface pretty much unusable.
So the fix for this is to not sort by read jobs, but by directory names
instead since they don't change all the time. The user can still sort by any
other column, but that sort is a momentary thing that might become invalid
moments later as data (accumulated sizes, number of child items) are
updated. Everybody please notice that **this is a known limitation** and any
complaints about that will flatly be rejected. The alternative would be to
not allow the user to sort at all during directory reading, and that is
certainly a lot less desirable.
- 2017-02-22
- @flurbius contributed a patch to switch the main window layout from tree
view above and treemap below to side-by-side (Menu _Treemap_ -> _Treemap as
Side Panel_).
- Added new document [GitHub-Workflow.md](https://github.com/shundhammer/qdirstat/blob/master/doc/GitHub-Workflow.md)
explaining how to work with GitHub and Git to contribute to QDirStat.
- 2017-02-20 Locating files by type from the _File Type Statistics_ window

You can now locate files with a specific filename extension directly:
- You select a file type (a filename extension) in the "File Type Statistics" window.
- You click "Locate" or you double-click the item.
- The "Locate Files" window opens.
- You click a directory there.
- In the main window, the branch for that directory opens, and all matching
files are selected in the tree view and in the treemap.
- You can now directly start cleanup actions for those files.
See also [GitHub issue #48](https://github.com/shundhammer/qdirstat/issues/48).
- 2017-02-18 New document: [QDirStat for Servers](https://github.com/shundhammer/qdirstat/blob/master/doc/QDirStat-for-Servers.md)
describing how to use QDirStat and the `qdirstat-cache-writer` script on
headless (no X server, no X libs) servers.
- 2017-02-17 _File Type Statistics_ window merged to Git master
Latest screenshot:

**Limitations:**
Since filename extensions (suffixes) don't have as much semantics in
Linux/Unix systems as they do in Windows, many files are categorized as
"Other". This is a known limitation, but it's a limitation of the whole
concept of using suffixes to categorize files by type. And no, checking file
headers for magic byte sequences like the "file" command does is not an
option here; QDirStat would have to do that for (at least) all the 30,000+
files typically listed under the "Other" category. So we'll have to live with
that limitation.
Next thing to come: Locating files with a specific suffix from there.
See [GitHub issue #48](https://github.com/shundhammer/qdirstat/issues/48).
- 2017-02-12 Working on a _File Type Statistics_ window
People who know WinDirStat inevitably want that _File Type_ view in QDirStat,
too. I was really reluctant to do that because I didn't quite see the point;
in WinDirStat, it serves mostly as a legend to the treemap colors since they
are constantly changing in WinDirStat: The file type that consumes most disk
space always gets color #1, the next-most color #2 etc., so it depends which
directory you scan what color each file type gets. In QDirStat, the colors
are stable; they are predefined and configurable in the _MIME Type
Categories_ configuration dialog.
And as most of you probably know, filename extensions have a much stricter
meaning in Windows than on Linux/Unix systems; Linux people get very creative
when it comes to using dots in filenames. Sometimes those dots delimit a
filename's extension (suffix) from its base name, sometimes they are used for
entirely different purposes.
Anyway, there was one user who was insistent enough to make me reconsider,
and I did some experimenting this weekend, and now we have an (albeit still
experimental) **File Type Statistics** view. So far, that code lives in a Git
branch, but I think it will stabilize in the next one or two weeks, so I will
merge it to Git master.
See the whole discussion with more screenshots at
[GitHub issue #45](https://github.com/shundhammer/qdirstat/issues/45)
- 2017-01-03 **New stable release: V1.2**
_Upgrading to this release is highly recommended for Btrfs users:_
If you used QDirStat to scan a Btrfs partition, any subvolumes of that
partition were not scanned (see
[GitHub issue #39](https://github.com/shundhammer/qdirstat/issues/39)).
Btrfs subvolumes were treated just like ordinary mount points (which, to all
intents and purposes, they are). So you might have wondered why the _df_
command shows your 40 GB root filesystem as 97% full, yet QDirStat shows only
about 7 GB. The rest might be hidden in subvolumes.
QDirStat stops reading at mount points - which only makes sense because
normally you want to know what eats up the disk space on that one partition
that is filling up, not on any others like /home that are mounted
there. Unfortunately, a Btrfs subvolume is also just another mount point, and
QDirStat would stop reading there, too - at /var/log, at /var/spool, at
/var/lib/libvirt etc.; a typical Btrfs root filesystem has about a dozen
subvolumes, and all files in them were disregarded by QDirStat.
This is now fixed: Despite Btrfs doing its best to make this difficult (using
one single privileged system call for all its functionality, including simple
info calls), QDirStat now detects if a mount point is a Btrfs subvolume and
continues reading if it is. QDirStat uses /proc/mounts (or, if this is not
available, /etc/mtab) to find this out.
This is fixed in the _qdirstat-cache-writer_ script, too.
- 2016-12-11 Bernhard Walle contributed some patches for MacOS X support.
Thanks, Bernhard!
- 2016-12-09 Fixed Perl (_qdirstat-cache-writer_) part of
[GitHub issue #39](https://github.com/shundhammer/qdirstat/issues/39):
QDirStat doesn't scan Btrfs subvolumes
The _qdirstat-cache-writer_ script now also checks the device names of a
mount point and its parent directory, not only their major/minor device
numbers; so now it will not stop at Btrfs subvolumes while scanning.
That script uses a more simplistic approach than QDirStat itself: It invokes
the _df_ command with that path and parses its output. If the path contains
very weird special characters, this may fail, in which case that directory
(which at that point is already known to have a different device major/minor
number than its parent) is considered a filesystem boundary, and that branch
is not scanned.
- 2016-12-08 Fixed C++ (QDirStat binary) part of
[GitHub issue #39](https://github.com/shundhammer/qdirstat/issues/39):
QDirStat doesn't scan Btrfs subvolumes
This was a bit of a challenge since the relevant Btrfs commands to obtain any
useful information about subvolumes all require root privileges, and I really
wouldn't want to scare users off by prompting for a _sudo_ password. QDirStat
now fetches the information from /proc/mounts (or /etc/mtab if /proc/mounts
is unavailable) and does some heuristics (which are not completely fool
proof) to check if a potential mount point is still on the same device. That
means that it will no longer treat a Btrfs subvolume as an ordinary mount
point where it stops reading by default, but it just continues. On the other
hand, another Btrfs mounted into the current filesystem is of course treated
as a normal mount point. See also the corresponding
[GitHub issue](https://github.com/shundhammer/qdirstat/issues/39)
for details.
The Perl _qdirstat-cache-writer_ still has the old behaviour, i.e. it still
stops at a subvolume mount point. This will be addressed next.
- 2016-12-07 Fixed [GitHub issue #40](https://github.com/shundhammer/qdirstat/issues/40):
Crash without useful error message when no display available
When ssh'ing without -X to a remote machine and starting QDirStat there, it
would just dump core and not issue any meaningful message. The fatal error
message was only in the log file:
` :0 (): QXcbConnection: Could not connect to display`
Now this message is also repeated on stderr, and in this particular case
("Could not connect to display"), it does not dump core anymore, but just
exits with error code 1.
- 2016-12-06 **Warning to Btrfs users** (Fixed as of 2012-12-09)
If you use QDirStat to scan a Btrfs partition,
[any subvolumes of that partition are not scanned](https://github.com/shundhammer/qdirstat/issues/39):
Btrfs subvolumes are treated just like ordinary
mount points (which, to all intents and purposes, they are). So you might
wonder why the _df_ command shows your 40 GB root filesystem as 97% full, yet
QDirStat shows only about 7 GB. The rest might be hidden in subvolumes.
QDirStat stops reading at mount points - which only makes sense because
normally you want to know what eats up the disk space on that one partition
that is filling up, not on any others like /home that are mounted
there. Unfortunately, a Btrfs subvolume is also just another mount point, and
QDirStat will stop reading there, too - at /var/log, at /var/spool, at
/var/lib/libvirt etc.; a typical Btrfs root filesystem has about a dozen
subvolumes, and all files in them are currently disregarded by QDirStat. You
can of course click on "Continue reading at mount point" individually in
QDirStat's directory tree for each one of them, but that's tedious.
I am working on a solution. One approach would be to check if the current
filesystem is Btrfs and list its subvolumes, but the Btrfs developers in
their infinite wisdom decided that `btrfs subvolume list ` is a
privileged operation, so QDirStat would have to use `sudo` with it and prompt
for the root password (at which point I as a user would terminate the program
and not use it anymore). **This is broken by design.** A simple info command
like that should not require root privileges.
- 2016-10-31 (Halloween) **New stable release: V1.1-Pumpkin**
It's about time for another official release to get the accumulated fixes and
small changes out into the world. Since today is Halloween, this release
shall be named _Pumpkin_ (as in the unforgettable Charlie Brown's _Great
Pumpkin_).
The last stable release, V1.0, was in mid-May (2016-05-16). Since then, there
were 5 bug fixes and one small feature (the config file split up into
independent parts so admins can provide presets to their users without
overwriting the complete configuration), all described in greater detail
below.
- 2016-10-23
- Fixed [GitHub issue #32](https://github.com/shundhammer/qdirstat/issues/32):
%p does not escape single quotes properly
If you have a file name like `Don't do this.txt` (with a quote character in
the name), the shell used when executing a cleanup action with this would
complain about unmatched single quotes.
QDirStat had always escaped such single quotes, but not the way common
shells (Bash, Zsh) expect it: They don't want a backslash in front of that
embedded single quote. Rather, you need to terminate the string with a
single quote, escape the embedded quote with a backslash (or put it into
double quotes), and then re-open the old string with another single quote.
Thus, `'Don't do this'` becomes `'Don'\''t do this'`.
This is certainly not what most people expect. I just wonder how much other
software is out there that does it the intuitive (yet wrong) way: Just
escape the single quote with a backslash (`'Don\'t do this'`).
Of course, such file names should be avoided entirely, but you can't help
some slightly broken MP3 ripper program doing it, so it needs to be handled
correctly.
- Fixed [GitHub issue #31](https://github.com/shundhammer/qdirstat/issues/31):
Segfault with cleanup action while reading directories
Now disabling cleanups that have a refresh policy other than "No Refresh"
while directory reading is in progress; otherwise the re-read when the
cleanup action has finished clashes with the directory read already in
progress.
This is not an optimal solution, but a very pragmatic one; the optimal
solution might queue updates and execute them after the main read is done.
- Fixed [GitHub issue #33](https://github.com/shundhammer/qdirstat/issues/33):
Added command line option `--slow-update` (or `-s`) for slow remote X connections.
- 2016-08-12
- Fixed [GitHub issue #23](https://github.com/shundhammer/qdirstat/issues/23):
The internal cache writer would sometimes generate incorrect cache files
because of buggy URL escaping resulting in an empty file name and thus
invalid cache file syntax. This affected file names with colons (which is
weird, but legal).
One of these days I'm going to throw out all that QUrl stuff and replace the
few things that I need with something that actually works consistently and
not just under optimum conditions.
- 2016-08-10
- Fixed [GitHub issue #22](https://github.com/shundhammer/qdirstat/issues/22):
Cache files containing the root filesystem would not display correctly or
segfault under certain conditions. This is now fixed.
- Added "Refresh All" action to the main window tool bar. I had consciously
avoided that because it's just too tempting to re-read the complete
directory tree rather than think about what actually might have changed and
then refresh just that, but it has become so common to use that action in
web browsers that I found myself missing that more and more. And re-reading
is not that expensive on today's mainstream PCs.
- 2016-07-02
- Fixed [GitHub issue #21](https://github.com/shundhammer/qdirstat/issues/21):
When started from a desktop menu, i.e. without any command line parameters,
QDirStat would not prompt for a directory to read, but read the current
directory (typically the user's home directory) right away.
- More graceful handling for nonexisting paths specified on the commmand
line: It now no longer just throws an exception right after starting the
program (which looks like a crash to the unwary user), but posts an error
popup instead and then asks for a directory to read.
- 2016-06-29
- V1.01 (Development version)
- Split up config file into four separate ones below ~/.config/QDirStat:
- QDirStat.conf
- QDirStat-cleanup.conf
- QDirStat-exclude.conf
- QDirStat-mime.conf
This should make it much easier for site administrators to provide their
own site-wide cleanup actions, exclude rules, or MIME categories. I did
this with this in mind:
http://moo.nac.uci.edu/~hjm/kdirstat/kdirstat-for-clusters.html
Here, they describe how users should overwrite their KDirStat config file
with one provided by the site admin so all users have those carefully
crafted cleanup actions. But that also means that all other settings get
lost each time there is a change in any of those commands, and users have
to update that config file again.
With the latest change, it is now possible to only replace the cleanup
action config (QDirStat-cleanup.conf) and leave everything else untouched.
Notice that this is far from a perfect solution; all cleanup actions the
user added himself still get lost. But doing this perfectly might pretty
quickly become an overengineered solution that would be hard to understand
for everybody.
As for migration from previous single-file configurations, QDirStat does
that automatically: It reads the single file and moves the respective parts
where they belong. No need to bother with any migration scrips or anything
like that.
- 2016-05-16 **First stable release: V1.0**
After 3 months of Beta phase and 3 Beta releases, here is finally the
official first stable release of QDirStat: Version 1.0.
In terms of source code, there were very little changes from the last Beta
(0.98-Beta3 from 2016-04-08) and no real code change (only the version number
increased) from the last check-in from 2016-04-11. This version can really be
considered stable in the truest sense of the word. It was not rushed out the
door, and there were no hectic last minute changes. It is well tested, and
the community had ample opportunity to report any problems.
- 2016-04-11
- _buxit_ reported
[GitHub issue #16](https://github.com/shundhammer/qdirstat/issues/16)
and contributed the fix for it shortly afterwards:
When clicking in the treemap, the corresponding item in the tree view was
not always scrolled into the visible area. Now it is.
- 2016-04-08
- Beta 3
- Fixed
[GitHub issue #15](https://github.com/shundhammer/qdirstat/issues/15):
After a cleanup action is executed that needs refreshing the affected
subtree, the parent directory is selected, which is intentional so the
user's focus is not thrown off completely. There was a bug when you
selected an item in the treemap afterwards, that change was not correctly
propagated to the internal selection model: The parent directory remained
selected (which was wrong), and the newly selected item was just added to
the selection, i.e. that item and (typically) its parent directory was
selected. When a potentially dangerous cleanup operation was now started,
it would affect not only that item, but also the directory; and, worse,
that directory often went out of the visible scope of the tree view. Yes,
the confirmation popup would ask for both of them, but you all know how
quickly users click away those popups without really reading them.
This bug is now fixed.
- Improved the confirmation popup. Now highlighting directories much more if
there is a "mixed" selection, i.e., both directories and non-directories
are selected at the same time:

- 2016-03-20
- Beta 2
Beta 1 has now been out for 6 weeks, and I have not received one single bug
report during that time. Maybe it's just business as usual, and people
just keep waiting for others to do the testing, while they themselves are
waiting for a stable release. Well, okay, so let them have their way: The
current code is now officially V0.92 Beta 2. And it won't be another 6
weeks; the next versions will come a lot more quickly. Once V1.0 final is
out, any bug reports will have to wait until there is time to work on
them. So, folks, use those Betas wisely.
BTW those who actually did test it will find that QDirStat is a lot more
stable even in Beta 1 than other pieces of software in their official final
release.
- 2016-02-27
- Debian / Ubuntu packaging contributed by Nathan Rennie-Waldock.
He also made a PPA repository available for various Ubuntu versions - see
[Ubuntu packages](https://github.com/shundhammer/qdirstat#ubuntu) below.
- 2016-02-06
- Added tab for exclude rules configuration to the config dialog (see
screenshot above). That's it: That was the last missing major feature.
**I hereby declare QDirStat to be Beta.**
_Please use the GitHub issue tracker for any bug reports._
- Exclude rules can now optionally match against the full path again. I had
changed this for just the directory name without the path by default, which
makes regexps a lot simpler. You can now select the old behaviour, too, if
you wish. This is configurable in the exclude rules tab of the config
dialog.
- Made the config file format of the new view header columns human readable
and editable. The first version from yesterday used the native format of
Qt's QHeaderView -- a QByteArray in hex encoding. This was a sorry excuse
for a settings format - not usable for anybody, not legible, much less
editable. Trolls, WTF? Pretty and usable formats everywhere else, and a
glorified (well, not even glorified) hexdump here?
I hope some admins who might want to provide ready-made config files for
their users will appreciate that. If not, this is just for consistency's
sake; I want to be able to read and edit my config file as I like, even
without any graphical config dialogs.
- The tree view now uses "middle eliding" for texts that don't fit into a
column. It used to elide at the end of the text, but that's not necessarily
useful for long file names; they often differ only at the end with lots of
text at the start in common. So, now it's no longer "VeryLongTextBlurb...",
but "VeryLongTe...foo.o" if anything needs to be cut off. Of course, this
makes most sense with the new column width modes, otherwise your column
will simply be resized wide enough to fit everything in.
- 2016-02-05
- Extended the context menu of the tree view header columns -- see latest
screenshot above. The configuration is now saved and restored when entering
the program. You can move the columns around (i.e. change their order),
hide columns, and choose between automatic column width ("auto size") or
setting it manually ("interactive size") for each column individually or
for all columns at once.
- You can now read a cache file directly from the command line:
````
qdirstat --cache cache-file
````
- Fixed GitHub issue #9:
[qdirstat-cache-writer creates broken cache file if some directory lacks Exec flag](https://github.com/shundhammer/qdirstat/issues/9)
- Fixed GitHub issue #10:
[incorrect handling of sparse files with 0 allocated blocks](https://github.com/shundhammer/qdirstat/issues/10)
- 2016-02-02
- Fixed a bug where directory names with a colon ":" were cut off when
reading a cache file, thus all files and directories below that point could
not find their parent directory, so that complete branch was cut off.
- Much improved performance for treemaps of large directory trees: Now not
rebuilding the treemap immediately when the user resizes the window or
drags the splitter dividing the main window, but just scheduling an update
in 200 milliseconds. If another rebuild is requested during this time, the
previous one is discarded. The net effect is that the treemap now is
rebuilt only once, not for every pixel size change of the treemap
subwindow, so the application remains responsive during dragging the
splitter or resizing the main window.
- 2016-02-01
- Fixed GitHub issue #6:
[NullPointerException when reading cache file](https://github.com/shundhammer/qdirstat/issues/6)
The DirTreeModel and the DirCacheReader were somewhat out of sync with
regard to which directory is ready for display in the tree view.
- 2016-01-30
- Added a context menu for the tree view header. It's still very limited, but
you can now turn off auto-resizing of the tree columns for the current
session.
- Added a .desktop file so QDirStat should now show up in the menu of the
major desktop environments (KDE, GNOME, Xfce, Unity, ...) and in their file
managers' "Open With" menus when you right-click a directory.
- 2016-01-29
- Since the missing tabs in the config dialog will also have a list of things
at the left and details of the one current item of those things at the
right, I tried to move out the common part of this as a base class. Since
the things those config tabs manage have different types, I tried a C++
template class. But **it turns out that in this year 2016 Qt's moc still
does not support templates. WTF?!**
- 21:00 (Grrrr) Okay, I found a workaround, albeit a pretty ugly one: Work
with void pointers and forced type casts. Yuck. That's being bombed back to
the early 1990s - we had to do this kind of stuff back with OSF/Motif in
plain C all the time. Type safety was unknown back then; you could get all
kinds of nasty surprises by casting pointers slightly wrong, and the
compiler had no chance (even if it hadn't been that crappy SunOS C
compiler, but a decent GCC) to catch any of this.
25 years later, and we are still stuck with that kind of stone age
programming - just because some tool never got ported to the 21st
century. Sigh.
Yet another day of develpment completely wasted due to insufficiencies of
underlying tools. Just great. I am getting fed up with this.
- 2016-01-22
- Improved usability of refreshing the tree after cleanup actions: They used
to leave the tree behind with nothing selected, the branch the user just
worked in closed (which is natural since it needed to be re-read from disk)
and scrolled to another position - maximum disorientation for the user. Now
the parent directory is selected, giving at least some hint where the
action took place. It's not optimal yet, but much better than before.
- Improved usability of the tree widget: When an item in the treemap is
selected, all other branches in the tree are now collapsed before the new
branch is opened. But this required working around some design flaws in the
underlying _QTreeView_ class.
**Rant:** Trolls, didn't it ever occur to you that if you are _constantly_
using that _d->expandedIndexes_ from _QTreeViewPrivate_ in the _QTreeView_
public class, derived widgets might need that information, too? There is
**no way** to access the currently expanded items other than cheating in
some creative way. Seriously, I am not going to duplicate that bookkeeping
with the _expanded()_ and _collapsed()_ signals, always being off by some
items or not getting the information that items were removed (or listen to
half a dozen more signals for even more advanced bookkeeping). If a widget
class cannot provide that kind of elementary information to its derived
classes, it's poorly designed. Period.
- 2016-01-18
- Applied Qt4 compatibility patches from Michael Matz. The only nontrivial
issue was a thin wrapper around QProcess to make it store the program to
execute and its arguments in the constructor and use those later with a
plain start() without any more arguments.
- 2016-01-16
- The MIME categories and the corresponding treemap colors can now be
configured - see screenshot above. Yes, this is a real treemap widget as a
preview for the colors, complete with a demo directory tree with a random
number of files with random sizes (i.e. it looks different for each
invocation). That part was the last major feature that was missing; now
it's only little stuff that's left (still quite a number of it, though).
- Treemap colors are now no longer fixed; there is now a rules engine called
MimeCategorizer. It uses a new class MimeCategory that groups MIME types
(by filename, not by magic numbers in the file) into broad categories like
"Documents", "Videos", "Music", "Images". Each of these categories has a
list of filename extensions that belong to it (".mp4", ".wmv", ".mov"
etc. for "Videos", for example). The categorizer uses a very fast lookup
map for the vast majority of the rules (simple file extensions), but it
can also use more powerful wildcards wherever you like them.
- The log file is now created per user: It's now /tmp/qdirstat-$UID.log,
which for most Linux home users (with only one user account on the
machine) is typically /tmp/qdirstat-1000.log .
- 2016-01-15
- Added new macros for use within cleanups: %terminal and %filemanager. They
are expanded to the terminal window or file manager application,
respectively, of the current desktop (KDE, GNOME, Xfce, ...). I just
wasted four hours (that could have been put to better use adding missing
features - grrrr) because KDE's konsole misbehaves in every way possible
(leading today's WTF count with 3):
- It won't let me start it in the background from within QDirStat; it
simply exits. I tried all kinds of command line arguments (--nofork,
--hold), I tried to wrap it into a subshell, into the _nohup_ command -
nothing helped. WTF?
- It exits when QDirStat exits. Well, since it won't let me start it in the
background, that's not too surprising. Still, if it does its own fork(),
WTF?
- It doesn't give a damn about the current directory you start it from, it
needs its --workdir command line argument. WTF?
- Added %d macro for cleanups: This is the directory name with full path. For
directories, this is the same as %p. For files, this is their parent
directory's %p.
- %terminal : Terminal window application of the current desktop; one of
- konsole
- gnome-terminal
- xfce4-terminal
- lxterminal
- eterm
- xterm (fallback)
- %filemanager : File manager application of the current desktop; one of
- konqueror
- nautilus
- thunar
- pcmanfm
- xdg-open (fallback)
- Which desktop is used is determined by the _$XDG_CURRENT_DESKTOP_
environment variable. Currently supported:
- KDE
- GNOME
- Unity
- Xfce
- Lxde
- Enlightenment
(no clue how to start its file manager, though - using xdg-open here)
- Users can override this with the _$QDIRSTAT_DESKTOP_ environment variable,
so you can get, say, the Xfce terminal or file manager despite currently
running KDE if you set
export QDIRSTAT_DESKTOP="Xfce"
- Of course, you can still simply use your favourite file manager if you
simply use its command instead of %filemanager in the default "Open File
Manager Here" cleanup action.
- Added new standard cleanup actions:
- Git clean. Start "git clean -dfx" in the current item's directory. This
is relevant for developers or for people who regularly build software
from Git repositories.
- Clear directory contents. This removes everything inside a directory, but
leaves the directory itself intact. ~/.thumbnails or browser cache
directories are typical candidates for this with their ever-growing
content: You probably want to keep the directory, but get rid of
everything inside it.
- Redefined the semantics of the _file manager_ cleanup action: It no longer
tries to open files with the corresponding application depending on MIME
type, it now always opens a file manager in that directory (which can open
the file in its app if you want that). It's now also renamed to "open file
manager here". If you still want the old behaviour, you can easily add your
own cleanup action with the "xdg-open %p" command.
- Added "Troubleshooting" section in this document.
- Cleanup actions that have an icon are now added to the tool bar. Right now,
only some of the predefined actions have an icon. There is currently no way
for the user to specify an icon for a cleanup action.
- 2016-01-13 Added "move to trash", this time as a normal action in the "Edit"
menu, the toolbar and the context menus. This is a real implementation of the
XDG Trash specification. It does not rely on outside tools that might or
might not be available.
- 2016-01-12 We have a first MacOS X port! Sonja Krause-Harder volunteered to
install a Qt development environment (11 GB! Yikes!) on her MacBook. I would
have expected some changes, but a simple "qmake; make" just did the
job. Amazing! -- The major challenge was to find where "qmake" gets installed
in that MacOS Qt environment.
- 2016-01-10 Went through the old KDirStat changelog and found a few bugs that
I had fixed there -- and promptly repeated with the new QDirStat:
- Disable cleanups while reading directories. This would result in a segfault.
- No longer showing the path of the current directory being read. This sped
up reading /usr on my machine from 9.5 sec to 1.5 sec (!).
- 2016-01-09 Cleaned up this README.md file. It had grown much too long.
- 2016-01-08 Cleanups are now configurable - see screenshot.
- Cleanup actions can now be added, deleted, and moved up or down the list.
There is no longer a hard limit to the number of cleanup actions; create as
many as you like. Of course, your screen size is still the limit for those
menus. ;-)
- In addition to the old cleanup parameters, you can now configure the output
window behaviour. The default is "show after timeout" with a timeout of
half a second. This may sound pretty short, but I started with 3 seconds
and found that it felt sluggish. A modern PC can get a lot of things done
in half a second; yet waiting for more than that feels like an eternity. So
if any action takes longer than that, an output window pops up. Of course,
if there is any error, it pops up anyway.
- You can now configure the shell to use. I was weighing the pros and cons of
always using either /bin/sh or the user's login shell, and I found that
there is no killer argument in favour or against either option. For
example, I use the _zsh_, and while it's a great interactive shell, it did
give me problems for that "remove junk files" cleanup: "rm -f *.o *.bak *~"
-- when any of the wildcards cannot be expanded because there is no such
file, it complains. Okay, you can wrap the whole command in "/bin/bash -c",
but that's yet another indirection, so now you can configuare /bin/bash for
that particular cleanup action. On the other hand, for some things I might
want my original shell environment, so I do want my login shell by default.
This is now the default behaviour: Try $SHELL (the user's login shell), and
if that environment variable is not set or whatever is set there is not
executable, it falls back to /bin/bash and then /bin/sh. And you can still
enter your own in an editable combo box (but not "ruby" or "perl" because
the "-c" option is still added automatically).
- 2016-01-05 I admit I had never really liked the way the output of cleanup
actions was typically hidden. Most of the times I couldn't care less, but
sometimes there were error messages that mostly went unnoticed - such as no
permissions to convert a directory into a compressed tarball. Now we have
something new: A process watcher window that looks very much like a terminal
window. The commands and their output are displayed there: Normal output
(stdout) in amber, error output (stderr) in red. It will be configurable for
each individual cleanup action if this window is desired: You can choose to
always open it, to not open it at all -- or to have it automatically open
when there is any output on stderr. And there is also a checkbox to
automatically close it when the cleanup process finishes successfully. This
is all not 100% perfect yet, but it works quite well already.
- 2016-01-04 Cleanups are back. They still need some work, and you'll have to
edit the config file in ~/.config/QDirStat/QDirStat.conf to configure
anything, but they work.
- 2016-01-03 We are getting nearer to the target:
- Settings are read from and written to the settings file in all relevant
places. This includes what columns to display and their order. See section
'Settings' below.
- Refreshing the selected tree branch, continuing reading at mount points and
at excluded directories now works.
- Context menus are back. I am somewhat proud of the way my new ActionManager
handles that with Qt introspection to avoid duplicating stuff: I wanted to
keep the QActions in the Qt Designer file. That ActionManager keeps a
pointer to the MainWindow that is the parent of all those QActions, and
attached views can search that widget tree for action names (yes, that
works only if you keep those QObject names tidy - which I am doing anyway).
- Found some more icons for those actions.
- Exclude rules are now greatly simplified. They no longer get the entire
path to match which requires quite complex regexps, they only get the last
path component - i.e., no longer "/work/home/sh/src/qdirstat/src/.git", but
only ".git". You can now even tell the exclude rule to use a simplfied
syntax: "FixedString" or "Wildcard" in addition to the normal "RegExp".
- Still missing (this list is getting considerably shorter):
- Cleanups
- Settings dialog
- 2016-01-01 New Year release
- Added mouse operations to the treemap. Some where there in the old kdirstat
(but I guess not many users knew about them), some are new:
- Left click: Select item and make it the current item.
- Ctrl+Left click: Add item to selection or toggle selection.
- Middle click: Select the current item's parent. Cycle back at toplevel.
- Double click left: Zoom treemap in.
- Double click middle: Zoom treemap out.
- Mouse wheel: Zoom treemap in or out.
- Reliably sort by pending read jobs while reading.
- Fixed crashes if wildly clicking in the tree while reading. Yes, I
know... "Doctor, it hurts when I do that!" - "Then don't do that."
- 2015-12-31 New Year's Eve release
- Added the URL of the current item in the status bar at the bottom of the
main window. If more than one item is selected, it displays the total sum
of all selected items there.
- Treemap zoom in / out / zoom reset works. The treemap now automatically
zooms out if an item outside its current scope is clicked in the tree view.
- Added more menu and toolbar actions and icons for many of them.
- The treemap's red "current item" rectangle is now stippled instead of a
solid line if the current item is not also selected (users can do that with
ctrl-click).
- Added "about" dialogs for the program and the used Qt version.
- 2015-12-30 Treemap rendering now works as expected, and selecting items
(including multi-selection with shift-click and ctrl-click in the
tree view and ctrl-click in the treemap view) works. It was a bit
of a challenge to avoid Qt signal ping-pong between the selection
model object and the two views.
- 2015-12-28 Treemaps are back. It's not perfect yet, but the basic rendering
works. I admit I was somewhat scared of that part, but the
transition from Qt3 QCanvas to QGraphicsScene / QGraphicsView
went much smoother than I had expected. I am very glad I don't
have to dig deep into the math again with those cushioned
treemaps; that part worked completely unchanged. :-)
- 2015-12-27 The tree view now supports _extended_ selection, i.e. you can
shift-click to select a range of items or ctrl-click to select or
deselect individual items. This was the most requested feature
for the last KDirStat. This means you can now select more than
one item at once to move it to the trash can etc. (once cleanup
actions are back).
- 2015-12-25 Christmas release
- Sorting is now done internally in the DirTreeModel, and it's blazingly
fast. It uses lazy sorting - postponing sorting until the last possible
moment for each tree branch. Maybe the branch will never get visible, and
then it doesn't need to be sorted at all. The QSortProxyModel is gone.
- Reading cache files finally works again. It was quite some hassle to find
all the places where the invisible root item that is required for the
QTreeView / QAbstractItemModel make a difference. I hope now I caught all
of them.
- Fixed some bugs that resulted in segfaults. Well, it's a development
version. Such things happen.
- Removed the section about K4DirStat in this README.md; that information was
outdated. It turns out I hadn't looked at the most recent sources of
K4DirStat - that was entirely my own stupidity. My apologies. Since right
now I don't have an informed opinion about K4DirStat, I preferred to remove
that section entirely for the time being. Looks like K4DirStat is indeed
ported to Qt5 now.
- 2015-12-20 First usable preview version - see screenshot above. It's still
pretty rough, and sorting via the QSortProxyModel seems to be
awfully slow once a number of tree branches were ever
opened. Looks like I'll have to do that myself, too.
- 2015-12-18 Found the crippling bugs that made the DirTreeModel do crazy
things. None of the Qt classes proved to be helpful to find that
- they just happily do the crazy things. That's what I call poor
design. Now there is a first working QDirStat with a useful
display tree, including icons (but no percentage bar graph yet).
- 2015-12-07 First working DirTreeModel -- still minimalistic, but working.
- 2015-12-06 Created tree model based on QAbstractItemModel.
Compiles, but dumps core so far.
- 2015-12-05 Imported and ported directory tree data classes.
Hammered through the compiler, but nothing usable so far.
- 2015-11-28 QDirStat project is being set up. Nothing usable so far.
## KDirStat
KDirStat is the predecessor to QDirStat. QDirStat is an 80% rewrite of the KDE3
based KDirStat.
KDirStat home page: http://kdirstat.sourceforge.net/
Sources: https://github.com/shundhammer/kdirstat
### KDirStat History
_(Incomplete list, just highlighting important releases)_
- 2006-06-01 KDirStat 2.5.3: The last KDE3 based version.
- 2006-01-08 KDirStat 2.5.2:
- New: Read and write cache files
- 2005-02-22 KDirStat 2.4.4
- New: Handle hard links and sparse files
- 2003-01-30 KDirStat 2.3.5
- New: colored treemap
- 2003-01-05 KDirStat 2.3.3
- New: Treemaps (monochrome only)
- Communication between treemap and tree list view: Select an item in one
view, and it is automatically selected in the other one, too.
- 2002-02-25 KDirStat 2.0.0
- Complete rewrite for KDE 2 / Qt 2
- Doing internal caching and (very) lazy creating of QListViewItems for
improved performance and resource consumption
- 2000-01-21 KDirStat 0.86 for KDE 1 announced -- the first public version.
qdirstat-1.8/doc/File-Age-Statistics.md 0000664 0000000 0000000 00000020173 14112476455 0020021 0 ustar 00root root 0000000 0000000 # The QDirStat File Age Statistics Window
See also [GitHub issue #172](https://github.com/shundhammer/qdirstat/issues/172).
QDirStat can break down the _age_ of files (based on their modification time)
in a subtree by year and, for the current year and the year before, by
months. This is strictly for files; directories, symlinks etc. are disregarded.
This is a new view opened from the menu with _View_ -> _Show File Age
Statistics_ or with the `F4` key. If a directory is selected, it starts with
that directory, otherwise with the complete subtree.

For each year, it shows:
- The number of files that were last modified in that year
- The percentage of those files relative to the selected subtree, both as a
percent bar and as a number
- The total size of files that were last modified in that year
- The percentage of those files relative to the selected subtree, both as a
percent bar and as a number.
## Breaking Down to Months
For the current year and the year before, you can expand the months (click on
the little arrows on the left).

## Directories with no Activity for some Years

The list always starts with the current year, even if there was no activity in
the subtree in that year (i.e. no file was modifed in that year). All inactive
years up to the last year with any activity are displayed.
This helps to quickly see at a glance that there was a while with no activity,
even without reading the year numbers.
## Drilling Down Deeper into Subdirectories
Simply leave the _File Age Statistics_ window open and click on another
directory in the main window's tree view, and the _File Age Statistics_ window
is automatically updated with the data for that directory.
You can also switch that behaviour off when you uncheck the _Sync with Main
Window_ check box at that bottom of the _File Age Statistics_ window. In that
case, you can always simply hit the `F4` key again to update the window.
## Locating Files from that Year / Month
If there are no more than 1000 files in the selected year or month, you can use
the _Locate_ button to open another pop-up window that lists those files. Click
on one of them to select it in the main window; the main window scrolls to that
branch, selects the file and updates the _Details_ panel with it.
This is limited to 1000 files because it becomes very unwieldy at some point,
and performance suffers heavily. If you find yourself wanting to see more than
1000 files in a subtree, break it down to deeper subdirectories (see above).
## Use Case
This view was inspired by the discussion in
[GitHub issue #165](https://github.com/shundhammer/qdirstat/issues/165)
where an admin requested this for his users that had accumulated large amounts
of data and lost their overview.
It had become necessary to move some of those data to archive media, but the
users had lost the overview what was current and what was not, i.e. which parts
were good candidates to be moved to archive media.
Imagine a large machine with a large storage array used by a great number of
scientists collecting research data over many years. Researchers come and go;
new ones take over their projects and their data for their research. Others
leave when they are finished with their degree. Even with a best effort of
documentation (which is wishful thinking to begin with), after some time it
becomes murky what set of research data is what, and which of them are in
active use. Somebody new will not dare to get rid of anything; even if that
only means moving it to archive media where it's less easily accessible.
While this _File Age Statistics_ is by no means a general solution, it can
contribute to regain some kind of overview: If a directory branch has been
completely unmodified for many years, this is an indication that it may not be
in active use.
Of course, this is not guaranteed: It is very well possible that they are
actively using the data sets from 1995, 2000, this year and the year before,
and the old data sets are a reference that does not change. Only the users can
really tell. But the file age may give them additional hints.
## Usage Hints
It depends on the use case which columns in the _File Age Statistics_ are more
important: The number of files in that year (or month) or their total
size. That's why both of them are displayed.
When it comes to the relevance of data in a subdirectory, the sheer number of
files may be important: Even a lot of small files that accumulated may distract
and get in the way, especially when scripting (`find` commands come to mind)
over large directory trees.
When that is not an issue, but disk space is running out, of course the total
size of those files may be more important.
One use case is showcased in
[GitHub issue #172](https://github.com/shundhammer/qdirstat/issues/172):
A photo collection that grew over the years. In that case, the number of files
is much more important than their total size: During those years, camera
technology rapidly advanced, moving from 3 Megapixels up to 10, then 12, then
24. That means that photos taken in earlier years with considerably less
Megapixels are of course much smaller, so for photo activity during those years
the size is not a good measure; but the number of photos per year is.
### Get an Overview Quickly
Start at the top of the subtree. Arrange the windows so you can see both the
important part of the main window and the _File Age Statistics_ window.
If the _File Age Statistics_ for the toplevel don't give a good overview (which
is likely), click on its first subdirectory in the main window's tree
view. Watch the _File Age Statistics_ window.
Then use the _Cursor Down_ key in the main window to go to the next
subdirectory. Watch the _File Age Statistics_ window; but it's enough to give
it just a glance: Watch how the inactive years (the greyed-out entries)
change. Move to the next subdirectory etc.; you will now have a first
impression on the age distribution among that first subdirectory level.
If that also doesn't shed much light, go to the next deeper subdirectory level
in the main window. Since the main window's tree view orders the directories by
size by default, starting from the top is most promising.
If repeating that over several subdirectory levels still doesn't give you an
overview, this may not be the right tool for the job; it's not a catch-all
solution for every situation.
## Related Discovery Actions
Don't forget that there are also actions in the _Discover_ menu to immediately
find the oldest and the newest files in a directory tree. This is meant for
individual (or at least small numbers) of very old or very new files.
## Related Main Window Tree View Columns
### Last Modified
In the main window, the _Last Modified_ tree column shows the latest
modification time in that subtree, but in _including_ directories and
symlinks. That may or may not be what you need; it depends on the task.
Notice that a directory's modification time is updated whenever a file is
created or deleted there, or whenever a file is moved to or out of that
directory.
### Oldest File
This may be little known since it is not enabled by default, but there is a
similar column _Oldest File_ in the main window's tree view that shows the
modification time of the oldest file (not directory, not symlink) in that
subtree. This may be useful to drill down the tree view for very old files.
To activate that column, switch to an appropriate main window layout
(preferable L2 or L3), right-click on the headers of the tree view to open the
context menu, then select _Hidden Colunns_ -> _Show Column "Oldest File"_.
This functionality may be superseded by the relatively new _Show Oldest Files_
action in the _Discover_ menu.
## Reference
- [GitHub issue #172](https://github.com/shundhammer/qdirstat/issues/172)
- [GitHub issue #165](https://github.com/shundhammer/qdirstat/issues/165)
qdirstat-1.8/doc/GitHub-Workflow.md 0000664 0000000 0000000 00000026711 14112476455 0017316 0 ustar 00root root 0000000 0000000 # GitHub Workflow for Open Source Projects
(c) 2017 Stefan Hundhammer
License: GNU Free Documentation License
This is the workflow used for Open Source projects like QDirStat and YaST.
Some of this is mandated by the tools used (git, GitHub), some of it is just
best practices.
## Overview
Even though GitHub hosts the original source code repositories for those
projects, you don't work directly in them. Rather, you create your own forked
repository (your _fork_), work in that one, and when you finished something you
want to contribute to the original repository (called _upstream_), you create a
pull request.
That pull request is reviewed by the owner of the original project or by or
senior team members. They might ask you for changes if anything in your pull
request does not meet the project's quality criteria or violates the coding
style. In that case, you add more commits to the pull request, and it is
reviewed again etc. until everybody is satisfied and it is either merged (which
is the normal case) or it is finally rejected (which is a very rare thing).
When your changes are merged, you pull or rebase your fork against _upstream_
again so it is up to date, and then you can freely work on new things.
One holy rule is that **upstream master always has to work**, even between
official releases. This is much easier to achieve when everybody works in their
own fork, preferably in their own branch of their own fork.
## Initial Setup
- If you don't have one yet, create a user account at
[GitHub](https://www.github.com).
- Make sure to upload your ssh key to your GitHub account.
[More info...](https://help.github.com/articles/connecting-to-github-with-ssh/)
- Log in at GitHub.
- Fork the original (upstream) repository to your GitHub account.
You now have your own repo with that name.
**But it does not automatically sync itself with the upstream repo** as
others commit changes there after you forked; you have to do that manually
(see below).
- In a shell on your working machine (preferably Linux), clone your forked repo
to that machine:
cd ~/src
git clone -o mine git@github.com:kilroy/qdirstat.git
Where _kilroy_ is your GitHub user name which is part of the URL of that
fork. **Make sure to use the "git@github" URL**, not the "https://" URL: The
https URL is only useful for pulling (i.e. for read-only access), not for
pushing (i.e. for read-write access). Since you also want to commit changes
to that repo, you need read-write access.
_mine_ is the name of that _remote_. The default would be _origin_, but that
might lead to confusion because we'll add _upstream_ in a moment, so there
will be two remotes. If you have the same distinct name for all your forks,
your life will be considerably easier. You might also call it the same as
your user name (_kilroy_) here. Just make sure you use the same one for all
your repos.
You now have an entry like this in your `.git/config` file in that newly
cloned repo:
[remote "mine"]
url = git@github.com:kilroy/qdirstat.git
fetch = +refs/heads/*:refs/remotes/kilroy/*
- Add the original repo (_upstream_) as another _remote_ so you can pull /
fetch from there to keep your fork up to date:
git remote add upstream git@github.com:shundhammer/qdirstat.git
You now have two _remote_ entries in your `.git/config`:
[remote "mine"]
url = git@github.com:kilroy/qdirstat.git
fetch = +refs/heads/*:refs/remotes/kilroy/*
[remote "upstream"]
url = git@github.com:shundhammer/qdirstat.git
fetch = +refs/heads/*:refs/remotes/huha/*
You can also check this with this command:
git remote -v
mine git@github.com:kilroy/qdirstat.git (fetch)
mine git@github.com:kilroy/qdirstat.git (push)
upstream git@github.com:shundhammer/qdirstat.git (fetch)
upstream git@github.com:shundhammer/qdirstat.git (push)
Notice there is no _origin_ as would be the default if we hadn't used
`-o mine` during `git clone`. If you forgot that, you can always rename a
remote later (this affects only your working copy, not the repo on the GitHub
server):
git remote rename origin mine
- Make sure your user name and e-mail address are up to date and valid in your
`$HOME/.gitconfig`:
[user]
name = Kilroy Taylor
email = kilroy@mydomain.com
You can also use separate user names and e-mail addresses for different
projects; simply edit .git/config in that project and add a `[user]` section
there.
That name and that e-mail address will be recorded for each commit you make,
so this is where your karma points go and how you will be known to the
community. So choose that name wisely. Real names are preferred, albeit not
enforced.
## Common Tasks
### Working in Your Fork
Your fork is yours. You can do there whatever you like. But if you want to
contribute to the upstream project, you should follow some simple rules:
- Keep your fork in sync with upstream as good as possible (see next section
about rebasing).
- Work in a feature branch for everything you do. This makes your life much
easier when a pull request takes some time to get accepted: You can quickly
switch between the pull request and add some more changes there to satisfy
the reviewers and the next feature you might already be working on.
- Prefix your branches with your user name so you can easily tell them apart
form any upstream branches.
Example:
You plan to work on a _transmogrify_ feature. So you start from _master_,
create a branch for that and check it out:
git checkout master
git branch kilroy-transmogrify
git checkout kilroy-transmogrify
Now work in that branch and commit your changes there. Don't forget to push it
to your GitHub fork every once in a while:
git push mine kilroy-transmogrify
At some point, prepare a pull request to get your changes upstream. But before
you do that, you should rebase your branch so it is in sync with upstream
(except for your changes, of course).
### Rebasing (Updating Your Fork)
As mentioned before, when you fork a repo at GitHub, this will not
automatically update itself. As new commits are added to the upstream repo,
your fork will increasingly get out of date, so you have to update it on a
regular basis.
There are two methods: `pull` and `fetch` / `rebase`. As long as you don't do
any changes in your fork, there is no noticable difference; but when you work
in your fork, i.e. when you commit changes there, `fetch` / `rebase` is highly
recommended to keep the "railway yard" of parallel branches with merge and fork
points in the `gitk` display to a minimum.
First, get the data from the remote server (GitHub):
git fetch --all
**Make sure to use `--all`, not `-a`** which is something different (yes, this
is a common, stupid, unnecessary pitfall of that git command).
If that command remains silent, there was no change, so everything was still up
to date. If it reports something like
remote: Counting objects: 21, done.
remote: Compressing objects: 100% (21/21), done.
...
it did fetch some changes. Notice that the changes are only in the `.git/`
subdirectory so far; they are not applied to your source tree yet.
Now **make sure you don't have any pending changes** anymore. Check with
git status
If it reports any pending changes, you can choose to commit them or to _stash_
them, i.e. put them into temporary storage:
git stash
you can later retrieve them with
git stash pop
Now rebase. Typically, you want to do that based on the _master_ branch of
_upstream_:
git rebase upstream/master
This basically checks where you branched off your working copy, then
temporarily takes away your commits from that point on, then applies the
commits from upstream that have accumulated in the meantime. As a last step, it
tries to apply your commits on top of all that.
Since git commits are basically little more than patches (diffs) on top of
patches, this may or may not work flawlessly. If you are lucky, your commits
still apply cleanly, and you are set: You successfully rebased your repo.
If any of your commits does not apply cleanly, you will have to resolve merge
conflicts and afterwards call
git rebase --continue
to get to the next commit.
When all is done, you can push the result to your fork. Since the rebase caused
the parent SHAs of your commits to change, you will need to force-push; this is
normal and expected.
git push -f mine master
or
git push -f mine branch-name
if you were working in a branch.
### Preparing a Pull Request for Upstream
When you have some changes you would like to get upstream (to contribute to the
upstream project), you create a _Pull Request_.
To do that, make sure those changes are in a separate branch. If you worked on
a separate feature branch like recommended earlier in this document, you can
simply use that one as the branch for the pull request.
But remember to stop working on new features in that branch. As soon as you use
a branch for a pull request, you only commit changes there that were requested
by the reviewers.
Before creating a pull request, rebase your branch against upstream/master once
more and make sure to push your changes (even the latest ones) to your fork:
git fetch --all
git rebase upstream/master
git push mine kilroy-transmogrify
After that, go to your fork in the GitHub web UI, select your branch and click
"New Pull Request". Fill the form with a meaningful description of your changes
and send it off. Now you will have to wait for feedback from the upstream
project owner.
In the meantime, you will probably want to continue working on more
things. Remember to leave the pull request branch alone during that time;
create a new one for your next changes. It is perfectly okay to base that new
branch on the last one that has now become a pull request:
git branch kilroy-hyperforble
git checkout kilroy-hyperforble
...(work in that branch...)
When you get feedback about your pull request from your reviewers, you might
have to add some more changes to the pull request branch. So switch to that
branch (stash or commit any pending changes to your new working branch during
that time):
git checkout kilroy-transmogrify
...(add requested fixes)...
git commit -am "Added code review changes"
git push mine kilroy-transmogrify
Remember that despite the fact that your branch has become a pull request, it
is still hosted in your fork (_mine_) rather than upstream, so you still have
to push to your fork, not to upstream (which you probably can't anyway because
of insufficient permissions).
After that, switch back to your working branch and continue working there:
git checkout kilroy-hyperforble
git stash pop # if you stashed any changes
### Updating Your Fork After Your PR is Merged
Remember that after your pull request has been merged, _upstream/master_ has
changed, so make sure to fetch and rebase:
git fetch --all
git checkout master
git rebase upstream/master
There should be no conflicts (provided you are only working in branches - which
you should).
Don't forget to push the new master to your fork, too:
git push mine master
No `-f` or `--force` needed here either if you only work in branches.
## Further Reading
https://guides.github.com/activities/contributing-to-open-source/
https://guides.github.com/
https://www.atlassian.com/git/tutorials/merging-vs-rebasing
https://www.udacity.com/course/how-to-use-git-and-github--ud775
qdirstat-1.8/doc/Installing.md 0000664 0000000 0000000 00000000165 14112476455 0016423 0 ustar 00root root 0000000 0000000 # Installing QDirStat
See [main document](https://github.com/shundhammer/qdirstat/blob/master/README.md#installing)
qdirstat-1.8/doc/Pkg-View.md 0000664 0000000 0000000 00000026307 14112476455 0015756 0 ustar 00root root 0000000 0000000 # The QDirStat Packages View
QDirStat can now visualize the file lists of installed packages:

I.e. files are now grouped by the package they belong to, and in each subtree
only the files that belong to the package are displayed: In this example, in
`/usr/bin` only the `chromium-browser` binary is displayed, not all the other
files in `/usr/bin`. This is intentional.
Notice that you can also see the grouping in the treemap.
A click on the toplevel item in the tree or on `Pkg:/` in the URL shows the
packages summary:

## Target Platforms
This works on all Linux distributions using one of those low-level package
managers:
- Dpkg
- RPM
- PacMan
...and of course all higher-level package managers that are based on any of
them. I.e.
- Debian
- Ubuntu / Kubuntu / Xubuntu / Lubuntu
- SUSE (openSUSE Tumbleweed or Leap, SLES)
- Red Hat (Fedora, RHEL)
- Arch Linux
- Manjaro
It can even handle _rpm_ installed as a foreign package manager on a _dpkg_
based system (and the other way round); it tries the primary package manager
first, then any others that are also installed.
Please notice that _apt_, _synaptic_, _zypper_, _pkgkit_ and whatnot are all
higher level package managers that ultimately use one of the low level ones, so
even if you only use a higher level package manager, it still works without
restriction.
## Package Selection
QDirStat can fetch the information for all installed packages (which may take a
while) or only for a subset (which is much quicker, of course):

This example shows all installed packages whose name starts with "emacs".
### GUI
Menu _File_ -> _Show Installed Packages_ opens this package selection dialog:

Enter the search pattern in the input field. The default match mode is _Auto_
which tries to guess a reasonable mode, but you can also explicitly select one
of
- Contains
- Starts with
- Exact match
- Wildcard (very much like in the shell)
- Regular expression
_Auto_ uses heuristics to make an educated guess. The default is "starts with",
but if the search pattern contains typical regexp special characters, it
interprets the pattern as a regular expression.
If it detects just `*` (not `.*`) or `?`, it uses _wildcard_.
If the first character is `=`, it uses _exact match_.
All match modes are case insensitive.
### Command Line: Pkg URLs
You can also start QDirStat with a `pkg:` or `pkg:/` URL from the command
line. This also implicitly uses _auto_ mode, so the same heuristics apply to
interpret the URL:
```
qdirstat pkg:/chrom
```
All packages starting with "chrom" or "Chrom" or "CHROM".
_Notice that all patterns are case insensitive -- mostly because distro makers
and packagers tend to get creative when to use uppercase characters in package
names, and most users can't remember when or why._
```
qdirstat pkg:/=emacs
```
Only package "emacs", not "emacs25" or any other starting with "emacs".
```
qdirstat "pkg:/*gtk*"
```
_Notice that you have to protect the `*` wildcards from the shell by escaping
them with quotes._
All packages that have "gtk" somewhere in their name.
```
qdirstat "pkg:/.*qt[45].*"
```
All Qt4 or Qt5 packages. Notice that the patterns are case insensitive.
```
qdirstat "pkg:/(firefox|mozilla|chrome|chromium|opera)"
```
All the well-known browsers on the system. Notice that regular expressions use
a partial match, so use the `^` and `$` anchors when appropriate.
### Command Line: No initial "Choose Directory" Dialog
If you don't pass a command line argument to QDirStat, it will by default open
a directory selection dialog. This can be avoided with the `-d` or `--dont-ask`
command line option:
```
qdirstat -d
```
Of course you can always simply click that dialog away with the _Cancel_
button, but it might be useful for `.desktop` files to have that command line
parameter.
## Behind the Scenes
QDirStat uses external commands to get the information, both the list of
installed packages and the file list for each of the selected packages.
It always fetches the complete package list and then does the filtering
internally based on the package filter/URL; it does not rely on how each
external package manager interprets any patterns.
Packages that are installed in multiple versions or for multiple architectures
are treated internally as separate packages.
To get the package list, QDirStat uses any of those commands:
```
dpkg-query --show --showformat='${Package} | ${Version} | ${Architecture} | ${Status}\n'
```
```
rpm -qa --queryformat '%{name} | %{version}-%{release} | %{arch}\n'
```
```
pacman -Qn
```
Then it parses the output of those commands, removes those that don't fit the
filter criteria and iterates over the remaining ones to get the file list for
each one with any of those commands:
```
dpkg-query --listfiles pkgname
```
```
rpm -ql pkgname
```
```
pacman -Qlq pkgname
```
Then for each file list entry QDirStat does the usual `lstat()` syscall to get
up-to-date information about it from the filesystem (the file lists also don't
contain any information other than the path, not even if it's a file or a
directory, much less the size).
As you can imagine, waiting for all those external commands to return
information takes a while, in particular when all installed packages are
selected to display.
The first version of this took about 3 minutes to fetch all the information for
a quite normal Xubuntu 18.04 LTS installation -- much longer than just reading
the complete root filesystem with cold kernel buffers.
This is why now QDirStat starts a number of those external commands in
parallel; the sweet spot turned out to be 6 of those processes at the same time
(whenever one is finished, a new one is started so there are always 6 of them
running). This improved the speed on the same machine to 54 seconds.
The number of background processes can be configured in
`~/.config/QDirStat/QDirStat.conf`:
```
[Pkg]
MaxParallelProcesses=6
```
For `dpkg` and `rpm` it now uses a single command that fetches the complete
file list, i.e. all file lists for all installed packages at once. This reduced
the time on the same machine to 38.5 seconds.
However, this is a tradeoff since fetching that complete file list and parsing
it takes some time, so this is useful only above a certain number of packages
(about 200). This limit can be configured in
`~/.config/QDirStat/QDirStat.conf`:
```
[Pkg]
MinCachePkgListSize=200
```
Below that, it uses multiple parallel single calls to get individual file
lists.
Together with more performance tuning it's now down to 6.5 seconds.
| sec | Version | Description |
|------:|------------|---------------------------------------------------------------------|
| 180.0 | ce3e793298 | First pkg view; sequential separate `dpkg -L` calls |
| 53.4 | 68038f0525 | Separate `dpkg -L` calls in multiple background processes |
| 38.5 | ce54879a48 | Single `dpkg -S "*"` call to get all file lists for all pkg at once |
| 37.7 | 45b0a7a941 | Use cache for `lstat()` syscalls |
| 24.6 | c50e9a7686 | Use slower update timer for tree view while reading |
| 6.5 | a1043a20fb | Keep tree collapsed during reading |
See also [GitHub Issue #101](https://github.com/shundhammer/qdirstat/issues/101).
## Limitations
### Cleanups
Some of the cleanup actions are still useful in the packages view, in
particular "Open Filemanager Here" or "Open Terminal Here".
With everything else, be really, really careful!
Since all the files in that display are by definition system files, think twice
before deleting any one of them. If in doubt, just don't do it.
Be even more careful when dealing with directories: Remember that you only see
that part of the directory that belongs to that package. There might be many
more files in such a directory; for most directories, this is almost
guaranteed.
If you identify a disk space hog with the packages view, it is strongly advised
that you use your package manager to try to get rid of it, i.e. uninstall that
package -- and even then only if you know really well what you are doing.
### Dependencies
QDirStat only displays the raw information in the packages view: Just the disk
usage of each package.
It does not and very likely will not display any dependencies of a package,
much less indirect dependencies. This is the package manager's job.
If you identified a package that uses a lot of disk space, you will very likely
find that some other package requires it, and yet another package requires that
one etc. until you get to the level where you can even recognize a package that
you actively use.
Big fat `libfoo-locale` might be required by `libfoo` which might be required
by `foomatic` which might be required by `bar-desktop-base` which may be
required by not only your favourite desktop environment, but also by your
favourite media player application `boomplayer`.
As a matter of fact, that is more the norm than the exception. Distro makers
usually don't include packages just for fun, but because they are needed or at
least useful in the context of your system.
### What...if Scenarios
It would have been very nice to to include a feature like "what would happen if
I tried to remove that package?", showing the user what other packages would
also need to be removed.
Most higher-level package managers such as `zypper` or `apt` have a _dry run_
feature that could be used for this: Try a dry run of removing the `libfoo`
package, and it will show you all the direct and indirect dependencies, so you
can make an informed decision if you really can (and want to) live without all
those packages.
But those commands tend to require root permissions, even for the _dry run_
mode, and a desktop program like QDirStat asking for your _sudo_ password to
get those root permissions might be scary (and for good reasons) to many users.
## Support for More Package Managers
It's not that hard to add more package managers to the existing set, but there
must be reasonable support for that by people who actively use that platform
and who have the know-how to identify and fix problems.
Check out the existing ones to get an idea; it's little more than copy & paste
programming. Finding the right external programs and the right parameters is
the major challenge; then there might be some minor programming work for
parsing the output.
https://github.com/shundhammer/qdirstat/blob/master/src/RpmPkgManager.h
https://github.com/shundhammer/qdirstat/blob/master/src/RpmPkgManager.cpp
https://github.com/shundhammer/qdirstat/blob/master/src/DpkgPkgManager.h
https://github.com/shundhammer/qdirstat/blob/master/src/DpkgPkgManager.cpp
https://github.com/shundhammer/qdirstat/blob/master/src/PacManPkgManager.h
https://github.com/shundhammer/qdirstat/blob/master/src/PacManPkgManager.cpp
qdirstat-1.8/doc/QDirStat-for-Servers.md 0000664 0000000 0000000 00000017317 14112476455 0020234 0 ustar 00root root 0000000 0000000 # QDirStat for Servers
## Executive Summary
QDirStat can be used for headless (no X server, no X libs) servers: It comes
with a Perl script qdirstat-cache-writer that can collect data on the
server. You just have to copy the data file from the server to your desktop
machine where you can view the data with the normal QDirStat application.
## Server-Side System Requirements
- Perl
- Some command to copy files to your desktop machine:
scp, ftp or whatever
## One-time Server Setup
Copy the qdirstat-cache-writer script to the server.
You can find that script in scripts/ in the QDirStat source directory or in
/usr/bin when you installed QDirStat as a binary package. Alternatively, you
can fetch it directly from GitHub:
ssh root@myserver
cd /usr/local/bin
wget https://github.com/shundhammer/qdirstat/raw/master/scripts/qdirstat-cache-writer
chmod 755 qdirstat-cache-writer
By all means, have a look inside to convince yourself that there is no
malicious code. It's a very simple script.
## Collecting Data on the Server Side
Like QDirStat itself, qdirstat-cache-writer limits its operation to one
filesystem. It does not by default descend into mounted filesystems. It scans
Btrfs subvolumes, though.
For each filesystem you wish to collect data from, create a qdirstat cache
file:
sudo qdirstat-cache-writer / myserver-root.cache.gz
sudo qdirstat-cache-writer /var myserver-var.cache.gz
sudo qdirstat-cache-writer /srv myserver-srv.cache.gz
...
You should invoke the script with root permissions (thus sudo) to make sure you
can read all the directories. The first parameter is the starting point of the
directory scan, typically that filesystem's mount point. The last parameter is
the name of the output file.
The default is .qdirstat.cache.gz which is useful for desktop machines, but not
for servers, so it is recommended to explicitly specify a name here.
You might consider collecting those data in a nightly cron job.
## Transfer Data to Your Desktop Machine
scp "root@myserver:~/tmp/*.cache.gz" ~/tmp
## View Data on Your Desktop Machine
qdirstat --cache ~/tmp/myserver-root.cache.gz
or
qdirstat -c ~/tmp/myserver-root.cache.gz
or start qdirstat and use "Read Cache File..." from the "File" menu.
## Limitations
You cannot use QDirStat's built-in cleanup operations, of course; they'd still
run on your desktop machine instead of your server. There is also no indication
that your are seeing the contents of a cache file rather than data collected
live from your local system, so be careful what you are doing.
## Security Concerns
Don't give a cache file to somebody you wouldn't trust to read all directories
on that server with root permissions. Don't even make it easily available to
such persons. If the directory contents include sensitive information, treat
the cache file with the same degree of confidentiality as you would the
original directory on the server.
## Why Not Use QDirStat over Remote X?
You can do that as well, of course. But that means you'll need at least the X11
libs and the Qt libs (Qt 5 by default) on the server. And you need to install
QDirStat on the server, too.
Also notice that with the advent of Qt 5, remote X has become very slow with Qt
applications: Qt 5 no longer uses Xlib / X protocol primitives for painting
(XDrawRectangle etc.), but renders into a pixel buffer and transfers that pixel
buffer. While this is a considerable speedup for local X, it is pretty slow for
remote X.
To ease that pain a little, QDirStat has a --slow-update (or -s) command line
option which is intended for remote X:
ssh -X myserver
qdirstat --slow-update
This makes QDirStat update its display only every 3 seconds rather than the
default 333 milliseconds during directory reading.
This interval can be configured in `~/.config/QDirStat/QDirStat.conf` :
[DirectoryTree]
SlowUpdateMillisec = 3000
## Looking Into a Cache File
A cache file is a gzipped text file, so it can be viewed with `zless`:
[qdirstat 1.0 cache file]
# Generated by qdirstat-cache-writer
# Do not edit!
#
# Type path size mtime
D /var 4096 0x53cef170
# Device: /dev/sda6
L run 4 0x54bbf0e3
L lock 9 0x54bbf0e3
D /var/cache 4096 0x58125237
D /var/cache/dictionaries-common 4096 0x53ceef0a
F hunspell.db 188 0x53ceef0a
F ispell-dicts-list.txt 0 0x53ceef0a
F wordlist.db 267 0x53cef022
F ispell.db 188 0x53ceef0a
F jed-ispell-dicts.sl 881 0x53cef024
F aspell.db 741 0x53cef024
F sqspell.php 366 0x53cef024
F emacsen-ispell-default.el 173 0x53ceef0a
F emacsen-ispell-dicts.el 897 0x53cef024
D /var/cache/cracklib 4096 0x53ceef8b
F cracklib_dict.pwi 22972 0x53ceef8b
F cracklib_dict.hwm 1024 0x53ceef8b
F src-dicts 104 0x53ceef8b
F cracklib_dict.pwd 412618 0x53ceef8b
D /var/cache/cups 4096 0x58a842ad
F job.cache 992 0x58a842ad
F ppd-updates 271 0x567b004a
The file format is described in detail in
[cache-file-format.txt](https://github.com/shundhammer/qdirstat/blob/master/doc/cache-file-format.txt).
In short, each line contains one entry for a file, directory, or symlink.
- The first field is the type: 'D' for directory, 'F' for file, 'L' for symlink.
- The second field is the name; for directories, that's always the full path, for
files, the path can be omitted.
- The third field is the size of the object (not including any child objects).
- The fourth field is the mtime in hex (seconds since 1970-01-01 00:00:00).
## Long file format
qdirstat-cache-writer -l /var /tmp/var.cache.gz
zless /tmp/var.cache.gz
[qdirstat 1.0 cache file]
# Generated by qdirstat-cache-writer
# Do not edit!
#
# Type path size mtime
D /var 4096 0x53cef170
# Device: /dev/sda6
L /var/run 4 0x54bbf0e3
L /var/lock 9 0x54bbf0e3
D /var/cache 4096 0x58125237
D /var/cache/dictionaries-common 4096 0x53ceef0a
F /var/cache/dictionaries-common/hunspell.db 188 0x53ceef0a
F /var/cache/dictionaries-common/ispell-dicts-list.txt 0 0x53ceef0a
F /var/cache/dictionaries-common/wordlist.db 267 0x53cef022
F /var/cache/dictionaries-common/ispell.db 188 0x53ceef0a
F /var/cache/dictionaries-common/jed-ispell-dicts.sl 881 0x53cef024
F /var/cache/dictionaries-common/aspell.db 741 0x53cef024
F /var/cache/dictionaries-common/sqspell.php 366 0x53cef024
F /var/cache/dictionaries-common/emacsen-ispell-default.el 173 0x53ceef0a
F /var/cache/dictionaries-common/emacsen-ispell-dicts.el 897 0x53cef024
D /var/cache/cracklib 4096 0x53ceef8b
F /var/cache/cracklib/cracklib_dict.pwi 22972 0x53ceef8b
F /var/cache/cracklib/cracklib_dict.hwm 1024 0x53ceef8b
F /var/cache/cracklib/src-dicts 104 0x53ceef8b
F /var/cache/cracklib/cracklib_dict.pwd 412618 0x53ceef8b
D /var/cache/cups 4096 0x58a842ad
F /var/cache/cups/job.cache 992 0x58a842ad
F /var/cache/cups/ppd-updates 271 0x567b004a
The only difference is that all entries are always specified with their full
path. That makes the file a bit larger, but now you can use it as a substitute
for the `locate` command:
zgrep cracklib /tmp/var.cache.gz
## Cache Files on Desktop Machines
See [scripts/README.md](https://github.com/shundhammer/qdirstat/blob/master/scripts/README.md)
qdirstat-1.8/doc/Shadowed-by-Mount.md 0000664 0000000 0000000 00000065147 14112476455 0017600 0 ustar 00root root 0000000 0000000 # Finding Files that are Shadowed by a Mount
(c) 2021 Stefan Hundhammer
License: GNU Free Documentation License
## Problem
If files are _shadowed_ by a mount, they are invisible, yet they still occupy
disk space.
For example, if your root filesystem contains an existing directory
`/home/kilroy` with 2 GB worth of files, but you also have a separate `/home`
filesystem that has an `/etc/fstab` entry, that separate `/home` fileystem is
mounted _over_ those files in `/home/kilroy`, making those 2 GB invisible and
unaccessible, no matter if the separate `/home` also has a `/home/kilroy`
directory. Of course those _shadowed_ files still occupy disk space; you just
can't see them.
What `QDirStat` or `du` report will be different from what `df` reports as
"used".
_Notice: If it's Btrfs, that is commonly caused by snapshots, subvolumes, CoW
and other Btrfs weirdness, so don't worry. See also
https://github.com/shundhammer/qdirstat/blob/master/doc/Btrfs-Free-Size.md._
## Low-tech Solution
Boot from live media (a Linux on a USB stick) or, if you have one, another
Linux installation on the same machine and mount that filesystem from there:
```console
tux@live-linux:~$ lsblk /dev/sdb
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb 8:16 0 931,5G 0 disk
├─sdb1 8:17 0 2G 0 part
├─sdb2 8:18 0 30G 0 part
├─sdb3 8:19 0 30G 0 part
├─sdb4 8:20 0 1K 0 part
└─sdb5 8:21 0 869,5G 0 part
tux@live-linux:~$ sudo mount /dev/sdb2 /mnt
tux@live-linux:~$ sudo du -hs /mnt/home
2.0G /mnt/home
```
The `lsblk` command is to find out what partition the root filesystem was.
After booting from a live system, your single disk will probably be `/dev/sdb`
since `/dev/sda` is typically the USB stick that you booted from. If you have
more disks, just use a plain `lsblk` command to see all your disks with all
your partitions.
On many live systems you can even install software packages, so you may find it
wortwhile to install QDirStat on your Ubuntu live system:
```console
tux@live-linux:~$ sudo apt install qdirstat
tux@live-linux:~$ xhost +
tux@live-linux:~$ sudo qdirstat /mnt
```
(Starting QDirStat with `sudo` to have permissions for all subdirectories)
# The True Linux Nerd Solution
We don't need no stinkin' reboot. We can do that while the system keeps running.
Why? **_Because we can!_**
...or you may have a storage setup that is slightly too complex to mount it
casually by hand; if you have full disk encryption or LVM or RAID or any
combination of those.
## General Idea
- Bind-mount the filesystem to have it accessible a second time, but without
other filesystems mounted on top of it.
- In that bind-mounted tree, bind-mount all subdirectories that are a mount
point in the original tree. Mount them all to a common parent to make it
easier to see all shadowed files (and only them) at once.
- Examine that tree, e.g. with QDirStat.
## WARNING
There is the potential of things going wrong in quite spectacular ways. If you
do things wrong, some bind-mounted directory might look like stuff that you
don't need, and you may feel compelled to delete a whole directory tree that
looks like a duplicated `/usr/lib` directory copied to a strange
location. Don't casually do that; it might be your _real_ `/usr/lib` that just
appeared a second time at that strange location, and if you delete it, you will
delete the real `/usr/lib`, and that will for sure wreck your system so you
will have to reinstall.
I have seen Linux system developers (not noobs!) do that by accident when
trying to reclaim disk space in their _Scratchbox_ cross-compilation
environment which also makes heavy use of bind-mounts (and symlinks).
Exercise extreme caution when handling anything that you found with this
method!
If you are not sure, better don't remove or even just rename or move
anything. Double-check what you are doing. Try to _create_ a file there
(`touch schlonz`) and then use a global `find / -name schlonz` to see where the
name appears; you may be surprised. **Then** make your decision.
Whatever you do with the instructions and script(s) presented here, **use at
your own risk**.
## Steps and Useful Commands
This is the manual solution. Scroll down for a simple script that does this for
the root filesystem and its direct mount points.
### 1. Bind-mount the Root Directory
```console
root@linux:~# mkdir -p /mnt/root
root@linux:~# mount -o bind / /mnt/root
```
### 2. Find all Real Mounts
- This lists the "real" mounts from `/proc/mounts`, ignoring the cruft (`/sys`,
`/proc`, `/dev`, `/run`) and any bind-mounts in `/mnt` that we might already
have created (in previous failed steps):
```console
root@linux:~# egrep -v ' /(sys|proc|dev|run|mnt)' /proc/mounts
/dev/sdc2 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
/dev/sdb2 /hd-root-18-04 ext4 rw,relatime,data=ordered 0 0
/dev/sdb3 /hd-root-14-04 ext4 rw,relatime,data=ordered 0 0
/dev/sdc3 /ssd-root-20-04 ext4 rw,relatime,data=ordered 0 0
/dev/sdc4 /ssd-work ext4 rw,relatime,data=ordered 0 0
/dev/sda1 /win/boot fuseblk rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,blksize=4096 0 0
/dev/sdb5 /work ext4 rw,relatime,data=ordered 0 0
/dev/sda2 /win/app fuseblk rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,blksize=4096 0 0
```
- Use only the second field (the mount points) from that:
```console
root@linux:~# egrep -v ' /(sys|proc|dev|run|mnt)' /proc/mounts | cut -d ' ' -f 2
/
/hd-root-18-04
/hd-root-14-04
/ssd-root-20-04
/ssd-work
/win/boot
/work
/win/app
```
- Ignore the root directory from that:
```console
root@linux:~# egrep -v ' /(sys|proc|dev|run|mnt)' /proc/mounts | cut -d ' ' -f 2 | grep -v '^/$'
/hd-root-18-04
/hd-root-14-04
/ssd-root-20-04
/ssd-work
/win/boot
/work
/win/app
```
### 2a. Caveat: Btrfs
Btrfs, being the _enfant terrible_ of filesytems that it is, needs special
treatment, as always.
When you bind-mount a Btrfs, you implicitly bind-mount its _subvolumes_, too
(tested on a recent openSUSE Tumbleweed from 3/2021). That means there is no
reasonable way to check if underneath all those mounted subvolumes there are
any shadowed files since even a bind-mount will shadow them immediately
again. Use the low-tech solution for that (see above: Booting from a live
system).
You can still check if the _other_ mounts (non-subvolume mounts) are shadowing
any files, though; but you need a few more steps for that, or you will drown in
all the stuff that is on the subvolumes because that will all show up in the
final result.
Unless, of course, you explicitly exclude the subvolumes as well. For that we
first need to find out on what device the root filesystem is:
```console
tux@linux:~> grep ' / ' /proc/mounts | cut -d ' ' -f 1
/dev/sda2
```
Or stored in a shell variable for later use:
```console
tux@linux:~> ROOT_DEVICE=$(grep ' / ' /proc/mounts | cut -d ' ' -f 1)
tux@linux:~> echo $ROOT_DEVICE
/dev/sda2
```
All the subvolumes are listed in `/proc/mounts` with that same device:
```console
tux@linux:~> grep $ROOT_DEVICE /proc/mounts
/dev/sda2 / btrfs rw,relatime,space_cache,subvolid=256,subvol=/@ 0 0
/dev/sda2 /boot/grub2/i386-pc btrfs rw,relatime,space_cache,subvolid=264,subvol=/@/boot/grub2/i386-pc 0 0
/dev/sda2 /boot/grub2/x86_64-efi btrfs rw,relatime,space_cache,subvolid=263,subvol=/@/boot/grub2/x86_64-efi 0 0
/dev/sda2 /opt btrfs rw,relatime,space_cache,subvolid=262,subvol=/@/opt 0 0
/dev/sda2 /var btrfs rw,relatime,space_cache,subvolid=258,subvol=/@/var 0 0
/dev/sda2 /root btrfs rw,relatime,space_cache,subvolid=261,subvol=/@/root 0 0
/dev/sda2 /srv btrfs rw,relatime,space_cache,subvolid=260,subvol=/@/srv 0 0
/dev/sda2 /usr/local btrfs rw,relatime,space_cache,subvolid=259,subvol=/@/usr/local 0 0
```
Now we can extend our pipeline from the previous section to exclude them all:
```console
tux@linux:~> grep -v "^$ROOT_DEVICE" /proc/mounts | egrep -v " /(sys|proc|dev|run|mnt)" | cut -d ' ' -f 2 | grep -v '^/$'
/tmp
/work/tmp
/work/src
/home
```
That's the list we need.
### 3. Bind-mount those Real Mounts
- Bind-mount one of those mount points:
```console
root@linux:~# mkdir -p /mnt/shadowed/work
root@linux:~# mount -o bind /mnt/root/work /mnt/shadowed/work
```
- Bind-mount more (or all) of them:
```console
root@linux:~# mkdir -p /mnt/shadowed/win_app
root@linux:~# mount -o bind /mnt/root/win/app /mnt/shadowed/win_app
root@linux:~# mkdir -p /mnt/shadowed/win_boot
root@linux:~# mount -o bind /mnt/root/win/app /mnt/shadowed/win_boot
```
Make sure not to again shadow directories while doing that; that's why this
example uses `/mnt/shadowed/win_app` and `/mnt/shadowed/win_boot`, not
`/mnt/shadowed/win/app` and `/mnt/shadowed/win/boot`. Use a flat list of target
mount points, not a tree. It's not a problem here, but it might be a problem if
there is more nesting, e.g. `/mnt/shadowed/var` and `/mnt/shadow/var/log`.
### 4. Check for Shadowed Files
By bind-mounting the mount points a second time to `/mnt/shadowed`, all files
that are not shadowed are now excluded; each file below `/mnt/shadowed` is a
shadowed one.
- Quick check with `du`:
```console
root@linux:~# du -hs /mnt/shadowed
```
This will report _something_ because directories also need a couple of disk
blocks; but it shouldn't be much, just about one _cluster_ (typically 4k) for
each directory.
- Check with `tree` (if you have it installed):
```console
root@linux:~# tree /mnt/shadowed
```
If you see more than just directories, you found your trouble spot.
- Check for files with `find`:
```console
root@linux:~# find /mnt/shadowed -type f
```
This better not find anything.
- Run QDirStat to see all the shadowed files:
```console
root@linux:~# qdirstat /mnt/shadowed
```
Notice that you can of course delete files with QDirStat in that setup. As
usual, be careful; maybe just move the files to another directory (one that is
not shadowed).
_Notice that you cannot delete, rename or move any of the bind mount points as
long as a mount is active on them: You will get an error "Device or resource
busy" if you try._
### Misc
`lsblk` shows all block devices (i.e. all disks and all partitions), no matter
if they are mounted or not. It doesn't need root permissions.
```console
sh@balrog:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 931,5G 0 disk
├─sda1 8:1 0 97,7G 0 part /win/boot
└─sda2 8:2 0 833,9G 0 part /win/app
sdb 8:16 0 931,5G 0 disk
├─sdb1 8:17 0 2G 0 part
├─sdb2 8:18 0 30G 0 part /hd-root-18-04
├─sdb3 8:19 0 30G 0 part /hd-root-14-04
├─sdb4 8:20 0 1K 0 part
└─sdb5 8:21 0 869,5G 0 part /work
sdc 8:32 0 232,9G 0 disk
├─sdc1 8:33 0 2G 0 part [SWAP]
├─sdc2 8:34 0 30G 0 part /
├─sdc3 8:35 0 30G 0 part /ssd-root-20-04
└─sdc4 8:36 0 170,9G 0 part /ssd-work
sr0 11:0 1 1024M 0 rom
```
`findmnt` shows all mounts with their mount hierarchy, even if a filesystem is
mounted to a mount point that is itself a mounted filesystem (i.e. not on the
root filesystem). It doesn't need root permissions.
```console
sh@balrog:~$ findmnt -t ext4,ext3,ext2,xfs,btrfs,fuseblk,vfat,vboxsf
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sdc2 ext4 rw,relatime,errors=remount-ro,data=ordered
├─/hd-root-14-04 /dev/sdb3 ext4 rw,relatime,data=ordered
├─/hd-root-18-04 /dev/sdb2 ext4 rw,relatime,data=ordered
├─/ssd-root-20-04 /dev/sdc3 ext4 rw,relatime,data=ordered
├─/ssd-work /dev/sdc4 ext4 rw,relatime,data=ordered
├─/win/boot /dev/sda1 fuseblk rw,relatime,user_id=0,group_id=0,default_permissions,allow_other
├─/win/app /dev/sda2 fuseblk rw,relatime,user_id=0,group_id=0,default_permissions,allow_other
└─/work /dev/sdb5 ext4 rw,relatime,data=ordered
```
Btrfs with mounted subvolumes and two VirtualBox _shared folders_:
```console
tux@linux:~> findmnt -t ext4,ext3,ext2,xfs,btrfs,fuseblk,vfat,vboxsf
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sda2[/@] btrfs rw,relatime,space_cache,subvolid=256,subvol=/@
├─/opt /dev/sda2[/@/opt] btrfs rw,relatime,space_cache,subvolid=262,subvol=/@/opt
├─/boot/grub2/i386-pc /dev/sda2[/@/boot/grub2/i386-pc] btrfs rw,relatime,space_cache,subvolid=264,subvol=/@/boot/grub2/i386-pc
├─/boot/grub2/x86_64-efi /dev/sda2[/@/boot/grub2/x86_64-efi] btrfs rw,relatime,space_cache,subvolid=263,subvol=/@/boot/grub2/x86_64-efi
├─/var /dev/sda2[/@/var] btrfs rw,relatime,space_cache,subvolid=258,subvol=/@/var
├─/root /dev/sda2[/@/root] btrfs rw,relatime,space_cache,subvolid=261,subvol=/@/root
├─/srv /dev/sda2[/@/srv] btrfs rw,relatime,space_cache,subvolid=260,subvol=/@/srv
├─/usr/local /dev/sda2[/@/usr/local] btrfs rw,relatime,space_cache,subvolid=259,subvol=/@/usr/local
├─/work/tmp work_tmp vboxsf rw,nodev,relatime
├─/work/src work_src vboxsf rw,nodev,relatime
└─/home /dev/sda4 ext4 rw,relatime,data=ordered
```
There doesn't seem to be a simple way to exclude all the kernel pseudo filesystems, i.e. a plain `findmnt` shows all the cruft, too:
```console
sh@balrog:~$ findmnt
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sdc2 ext4 rw,relatime,errors=remount-ro,data=order
├─/sys sysfs sysfs rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/security securityfs securityf rw,nosuid,nodev,noexec,relatime
│ ├─/sys/fs/cgroup tmpfs tmpfs ro,nosuid,nodev,noexec,mode=755
│ │ ├─/sys/fs/cgroup/unified cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelega
│ │ ├─/sys/fs/cgroup/systemd cgroup cgroup rw,nosuid,nodev,noexec,relatime,xattr,na
│ │ ├─/sys/fs/cgroup/blkio cgroup cgroup rw,nosuid,nodev,noexec,relatime,blkio
│ │ ├─/sys/fs/cgroup/hugetlb cgroup cgroup rw,nosuid,nodev,noexec,relatime,hugetlb
│ │ ├─/sys/fs/cgroup/perf_event cgroup cgroup rw,nosuid,nodev,noexec,relatime,perf_eve
│ │ ├─/sys/fs/cgroup/cpu,cpuacct cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpu,cpua
│ │ ├─/sys/fs/cgroup/net_cls,net_prio cgroup cgroup rw,nosuid,nodev,noexec,relatime,net_cls,
│ │ ├─/sys/fs/cgroup/cpuset cgroup cgroup rw,nosuid,nodev,noexec,relatime,cpuset
│ │ ├─/sys/fs/cgroup/pids cgroup cgroup rw,nosuid,nodev,noexec,relatime,pids
│ │ ├─/sys/fs/cgroup/rdma cgroup cgroup rw,nosuid,nodev,noexec,relatime,rdma
│ │ ├─/sys/fs/cgroup/memory cgroup cgroup rw,nosuid,nodev,noexec,relatime,memory
│ │ ├─/sys/fs/cgroup/freezer cgroup cgroup rw,nosuid,nodev,noexec,relatime,freezer
│ │ └─/sys/fs/cgroup/devices cgroup cgroup rw,nosuid,nodev,noexec,relatime,devices
│ ├─/sys/fs/pstore pstore pstore rw,nosuid,nodev,noexec,relatime
│ ├─/sys/kernel/debug debugfs debugfs rw,relatime
│ ├─/sys/fs/fuse/connections fusectl fusectl rw,relatime
│ └─/sys/kernel/config configfs configfs rw,relatime
├─/proc proc proc rw,nosuid,nodev,noexec,relatime
│ └─/proc/sys/fs/binfmt_misc systemd-1 autofs rw,relatime,fd=32,pgrp=1,timeout=0,minpr
│ └─/proc/sys/fs/binfmt_misc binfmt_misc binfmt_mi rw,relatime
├─/dev udev devtmpfs rw,nosuid,relatime,size=8168840k,nr_inod
│ ├─/dev/pts devpts devpts rw,nosuid,noexec,relatime,gid=5,mode=620
│ ├─/dev/shm tmpfs tmpfs rw,nosuid,nodev
│ ├─/dev/mqueue mqueue mqueue rw,relatime
│ └─/dev/hugepages hugetlbfs hugetlbfs rw,relatime,pagesize=2M
├─/run tmpfs tmpfs rw,nosuid,noexec,relatime,size=1638392k,
│ ├─/run/lock tmpfs tmpfs rw,nosuid,nodev,noexec,relatime,size=512
│ └─/run/user/1000 tmpfs tmpfs rw,nosuid,nodev,relatime,size=1638388k,m
│ └─/run/user/1000/gvfs gvfsd-fuse fuse.gvfs rw,nosuid,nodev,relatime,user_id=1000,gr
├─/hd-root-14-04 /dev/sdb3 ext4 rw,relatime,data=ordered
├─/hd-root-18-04 /dev/sdb2 ext4 rw,relatime,data=ordered
├─/ssd-root-20-04 /dev/sdc3 ext4 rw,relatime,data=ordered
├─/ssd-work /dev/sdc4 ext4 rw,relatime,data=ordered
├─/win/boot /dev/sda1 fuseblk rw,relatime,user_id=0,group_id=0,default
├─/win/app /dev/sda2 fuseblk rw,relatime,user_id=0,group_id=0,default
└─/work /dev/sdb5 ext4 rw,relatime,data=ordered
```
That's why it is advisable to explicitly specify `-t` with the filesystem types
that should be listed, otherwise you get drowned in all that _cgroup_
etc. garbage.
### Clean Up (Unmount all the Bind Mounts)
- Find all the mounts in `/mnt/shadowed`
- Unmount each one of them
- Unmount `/mnt/root`
- Remove the mount directories:
```console
root@linux:~# rmdir /mnt/shadowed/*
root@linux:~# rmdir /mnt/shadowed
root@linux:~# rmdir /mnt/root
```
Don't just use `rm -rf`; if there is still anything else than those
directories, something (some `umount`?) went wrong. You might accidentially
remove a whole directory tree on your root filesystem, wrecking your system in
the process. `rmdir` on the other hand is safe: It complains if the directory
is not empty.
----------------------------------------------------------------------
# The Script
This is a script that works for standard situations where files on the root
filesystem are shadowed by one or more direct mounts.
This does not cover shadowed files on another filesystem, e.g. a separate
`/var` filesystem with files in `/var/log` shadowed by a separate `/var/log`
filesystem mounted over it. That's easy to recover from by simply unmounting
`/var/log`.
This also does not work with crazy mount point names (or paths) with blanks or
other characters that make the shell barf. _If you do that, you clearly deserve
punishment, so you have to do it manually._ ;-)
But it supports a Btrfs root filesystem (including handling the subvolumes).
## Fetch the Latest Version
```console
tux@linux:~/tmp> wget https://raw.githubusercontent.com/shundhammer/qdirstat/master/scripts/shadowed/unshadow-mount-points
```
or use `curl` if you prefer that. Or use your web browser: Go to
https://github.com/shundhammer/qdirstat/tree/master/scripts/shadowed
and use "Save linked content as..." from the browser's context menu (right
click).
In any case, make sure the script is executable:
```console
tux@linux:~/tmp> chmod 755 unshadow-mount-points
```
## Dry run
To see what it _would_ do without actually doing it, use the `-n` (dry run)
command line option and call it as a normal user:
```console
tux@linux:~/tmp> ./unshadow-mount-points -n
*** Dry run - not executing any dangerous commands. ***
mkdir -p /mnt/root
mount -o bind / /mnt/root
mkdir -p /mnt/shadowed
mkdir -p /mnt/shadowed/tmp
mount -o bind /mnt/root/tmp /mnt/shadowed/tmp
mkdir -p /mnt/shadowed/work_tmp
mount -o bind /mnt/root/work/tmp /mnt/shadowed/work_tmp
mkdir -p /mnt/shadowed/work_src
mount -o bind /mnt/root/work/src /mnt/shadowed/work_src
mkdir -p /mnt/shadowed/home
mount -o bind /mnt/root/home /mnt/shadowed/home
tux@linux:~/tmp> ls -lR /mnt
/mnt:
total 0
tux@linux:~/tmp> grep '/mnt' /proc/mounts
tux@linux:~/tmp>
```
It did not execute any of the `mount` of `mkdir` commands; it just shows you
what it would do. This gives you the chance to copy & paste them to a file and
execute them one by one if you prefer that.
## Execute the Commands
Start the script without the `-n` (dry run) command line option, but with root
privileges (`sudo` or `su`, whichever you prefer):
```console
tux@linux:~/tmp> ./unshadow-mount-points
unshadow-mount-points: FATAL: This needs root privileges.
```
_Nope, this doesn't work. Use `sudo` or `su`._
```console
tux@linux:~/tmp> sudo ./unshadow-mount-points
mkdir -p /mnt/root
mount -o bind / /mnt/root
mkdir -p /mnt/shadowed
mkdir -p /mnt/shadowed/tmp
mount -o bind /mnt/root/tmp /mnt/shadowed/tmp
mkdir -p /mnt/shadowed/work_tmp
mount -o bind /mnt/root/work/tmp /mnt/shadowed/work_tmp
mkdir -p /mnt/shadowed/work_src
mount -o bind /mnt/root/work/src /mnt/shadowed/work_src
mkdir -p /mnt/shadowed/home
mount -o bind /mnt/root/home /mnt/shadowed/home
=== Found 447 shadowed files.===
=== Disk space in shadowed directories:
0 /mnt/shadowed/home
0 /mnt/shadowed/tmp
0 /mnt/shadowed/work_src
49M /mnt/shadowed/work_tmp
Now run qdirstat /mnt/shadowed.
Remember to later clean everything up with
unshadow-mount-points -c
```
## Analyze the Shadowed Files
If there were any shadowed files, use the tools of your choice to find out what
they are.
```console
tux@linux:~/tmp> qdirstat /mnt/shadowed
```
```console
tux@linux:~/tmp> tree -d /mnt/shadowed/
/mnt/shadowed/
├── home
├── tmp
├── work_src
└── work_tmp
└── hidden-treasure
└── qdirstat
├── debian
│ └── source
├── doc
│ └── stats
├── man
├── screenshots
├── scripts
│ ├── pkg-tools
│ └── shadowed
├── src
│ └── icons
│ ├── tree-medium
│ └── tree-small
└── test
├── data
└── util
22 directories
```
Compared with its counterpart in the root filesystem that has another
filesystem mounted over it:
```console
tux@linux:~/tmp> tree -d /work/tmp
/work/tmp
0 directories
```
```console
tux@linux:~/tmp> du -h /mnt/shadowed/
0 /mnt/shadowed/tmp
4.0K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/.github
4.0K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/debian/source
24K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/debian
100K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/doc/stats
344K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/doc
64K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/man
8.0M /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/screenshots
40K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/scripts/pkg-tools
8.0K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/scripts/shadowed
112K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/scripts
420K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/src/.moc
56K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/src/icons/tree-medium
56K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/src/icons/tree-small
232K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/src/icons
41M /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/src
28K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/test/data
4.0K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/test/util
32K /mnt/shadowed/work_tmp/hidden-treasure/qdirstat/test
49M /mnt/shadowed/work_tmp/hidden-treasure/qdirstat
49M /mnt/shadowed/work_tmp/hidden-treasure
49M /mnt/shadowed/work_tmp
0 /mnt/shadowed/work_src
0 /mnt/shadowed/home
49M /mnt/shadowed/
```
```console
tux@linux:~/tmp> find /mnt/shadowed -type f | wc -l
447
```
## Delete or Move the Shadowed Files
You can delete or move anything **below** any of the directories in
`/mnt/shadowed` if you are absolutely sure what it is; read the
[warning above](#warning):
```console
tux@linux:~/tmp> sudo mv /mnt/shadowed/work_tmp/hidden-treasure .
```
or
```console
tux@linux:~/tmp> sudo rm -rf /mnt/shadowed/work_tmp/hidden-treasure
```
But you can't delete or move any of the bind mount points themselves (because
they are active mount points):
```console
tux@linux:~/tmp> sudo rm -rf /mnt/shadowed/work_tmp
rm: cannot remove '/mnt/shadowed/work_tmp': Device or resource busy
tux@linux:~/tmp> sudo mv /mnt/shadowed/work_tmp .
mv: cannot remove '/mnt/shadowed/work_tmp': Device or resource busy
```
## Clean Up: Unmount all those Bind Mounts
The same script that sets up the bind mounts can also tear them down; use the
`-c` (clean up) option. Of course that also needs root permissions. This also
supports a dry run (`-n`) so you can see what it _would_ do.
```console
tux@linux:~/tmp> ./unshadow-mount-points -n -c
Cleaning up
*** Dry run - not executing any dangerous commands. ***
umount /mnt/shadowed/tmp
umount /mnt/shadowed/work_src
umount /mnt/shadowed/work_tmp
umount /mnt/shadowed/home
rmdir /mnt/shadowed/*
rmdir /mnt/shadowed
umount /mnt/root
rmdir /mnt/root
Mounts below /mnt:
/dev/sda2 /mnt/root btrfs
/dev/sda2 /mnt/shadowed/tmp btrfs
/dev/sda2 /mnt/root/mnt/shadowed/tmp btrfs
/dev/sda2 /mnt/shadowed/work_src btrfs
/dev/sda2 /mnt/root/mnt/shadowed/work_src btrfs
/dev/sda2 /mnt/shadowed/work_tmp btrfs
/dev/sda2 /mnt/root/mnt/shadowed/work_tmp btrfs
/dev/sda2 /mnt/shadowed/home btrfs
/dev/sda2 /mnt/root/mnt/shadowed/home btrfs
```
```console
tux@linux:~/tmp> sudo ./unshadow-mount-points -c
Cleaning up
umount /mnt/shadowed/tmp
umount /mnt/shadowed/work_src
umount /mnt/shadowed/work_tmp
umount /mnt/shadowed/home
rmdir /mnt/shadowed/*
rmdir /mnt/shadowed
umount /mnt/root
rmdir /mnt/root
Mounts below /mnt:
tux@linux:~/tmp> ls -lR /mnt
/mnt:
total 0
tux@linux:~/tmp> grep "/mnt" /proc/mounts
tux@linux:~/tmp>
```
## Clean-up Troubleshooting
If anything went wrong, it's safe to call it again; that might be useful if one
of the mounts is busy. You might have another shell in another terminal window
running that has one of the mounts as its current working directory. Close that
shell / that terminal window and just call it again:
```console
tux@linux:~/tmp> sudo ./unshadow-mount-points -c
```
If all else fails and you got tangled up in a mess of bind-mounts or if you
accidentially unmounted things like `/proc`, `/dev` or `/sys`, simply reboot.
**Caveat:** Do not use `sudo fuser -mk /dev/sda..` on that device since it's
your root filesystem: It will kill most of the processes on your machine,
including your desktop and your login session; every process that uses a
directory on the root filesystem as its current working directory and every
process that has any file on the root filesystem open.
qdirstat-1.8/doc/Troubleshooting.md 0000664 0000000 0000000 00000006175 14112476455 0017515 0 ustar 00root root 0000000 0000000
## Troubleshooting
### Can't Move a Directory to Trash
QDirStat does not copy entire directory trees to the trash directory in your
home directory. It tries its best to copy single files there, but for anything
larger, it strictly sticks to the XDG trash specification. So, if you have a
separate /home partition (which is strongly recommended for a lot of reasons),
you cannot move a directory from /tmp to trash because that would mean to move
a directory across filesystems -- from /tmp/somewhere to your
~/.local/share/Trash .
But there is an easy workaround. It's described in the XDG trash spec, but here
is a simple recipe what you can do:
Create a dedicated trash directory on the toplevel (mount point) of that file
system. If it is mounted at /data, do this:
cd /data
sudo mkdir .Trash
sudo chmod 01777 .Trash
Permissions '01777' means "rwx for all plus sticky bit". The sticky bit for a
directory means that only the owner of a file can remove it. The sticky bit is
required for security reasons and by the XDG trash spec (it's also required by
the spec that applications like QDirStat refuse to use that trash directory it
if it is not set).
Now you can move directory trees from /data/somewhere to the trash with
QDirStat. It will end up in /data/.Trash/1000/files/somewhere (if 1000 is your
numerical user ID which is common in Linux for the first created user). Your
desktop's native trash application (your trash icon on the desktop and the file
manager window you get when you click on it) should show it, and you can empty
the trash from there.
In Xfce, this works out of the box. KDE might need a forced refresh (press F5)
in that window.
For USB sticks, this explicit toplevel .Trash directory is usually not
necessary: If you have write permission on its toplevel directory, QDirStat
will (again in compliance to the XDG trash specification) create a trash
directory .Trash-1000 in its toplevel directory which is the fallback if there
is no .Trash directory there. This would also happen automatically on /data and
/ if you had write permission there -- which is, however, very uncommon.
What the major desktops (KDE, GNOME, Xfce) usually do with their native file
managers is to recursively copy the entire directory tree to your home trash
directory and then remove the original. Not only is this time-consuming and
wasteful (copy stuff before deleting?!), it might also be error-prone if that
directory tree contains symlinks, sockets or even just sparse files; and
permissions and timestamps (mtime, ctime, not to mention atime) might or might
not be the same as before. This might become a problem if you decide to restore
that directory tree from the trash.
I thought about emulating this behaviour, but this basically means to
reimplement large parts of what the _rsync_ command does (calling _rsync_ from
within QDirStat might not be such a good idea - what if it's not available or
anything goes wrong?), and frankly, I don't want to do that - in particular not
for something that typically gets deleted shortly afterwards anyway upon "empty
trash".
So, if you have this problem, please use the .Trash directory workaround
described above.
qdirstat-1.8/doc/Unpkg-View.md 0000664 0000000 0000000 00000026615 14112476455 0016323 0 ustar 00root root 0000000 0000000 # The QDirStat Unpackaged Files View
QDirStat can now visualize the files in system directories that are not
packaged, i.e. that are not part of any file list of any installed software
package.
This reads the complete file lists first (i.e. all file lists from all
installed packages), then reads the requested directory as usual and puts the
files that are packaged in a special branch `` in the tree view.
Those files are _not_ displayed in the treemap, i.e. the treemap now only
contains unpackaged files.
## What is this Good For?
- Recovering a wrecked system after botched upgrades
- Recovering from too much `sudo make install`
- Fixing packaging problems, e.g. find leftover shared libs that tend to get in
the way
- QA for distro release managers, QA engineers, PMs
- Satisfying user curiosity
- _Because we can!_ ;-)
## Starting the Unpackaged Files View
Menu "File" -> "Show Unpackaged Files" opens this dialog:

Select the starting directory from the combo box or start typing (it has
directory name completion) to enter the path of an existing directory.
A number of directories are excluded because they are expected to contain a lot
of unpackaged files. You can add more directories here (or remove ones from the
default list).
_`/usr/lib/sysimage/rpm` is the RPM database; you can safely leave that
directory there even on non-RPM systems because it doesn't exist on such
systems._
"Ignore Patterns" are wildcard patterns that are ignored in addition to the
packaged files. `*.pyc` (byte-compiled Python files) is there because Python
packages tend to leave behind a zillion unpackaged files of that kind that
would otherwise very much be in the way when exploring the result.
You can add more wildcard patterns here. If a pattern does not contain a slash,
only the filename is used for matching. If it does contain a slash, the
complete path is used.
Notice that a wildcard matches any levels of directories, so you could for
example use `*/__pycache__/*` to ignore all files in all Python cache
directories everywhere.
All changes in this dialog are saved for the next use, including starting that
view from the command line (e.g. `qdirstat unpkg:/usr/share`).
## Analyzing the Result

_Notice that the treemap now only contains unpackaged files. Each of the
colored rectangles corresponds to one unpackaged file._
This screenshot shows some files that obviously belong to Qt 5 (judging from
the `/usr/share/qt5` path) on openSUSE Tumbleweed, but that are not in the file
list of any package. Is that a bug or not? It is still possible that some
post-uninstall script removes them, but it is also possible that they will be
left behind when the packages are uninstalled.
Notice the greyed-out ignored directories which only contain files that are
properly packaged. Those `` branches are there to give you some
perspective what else is in each directory; otherwise users might be tempted to
believe that the unpackaged files are all that there is, and maybe remove that
entire directory and thus wreck the system.

This screenshot shows a custom Grub2 font that was manually created to have a
larger, much better readable boot font on a high-resolution monitor. That one
file clearly stands out from all the packaged files there.
`/boot/grub2` and `/etc` are some of those directories that contain a wild
mixture of packaged and unpackaged files; some are generated, some are just
backups of the previous version, some were created as templates for users to
edit.
### Ignored Files
In this view, all files that are in the file list of any installed package are
ignored. As a result, there are many directories that don't contain any
unpackaged file; that should actually be the norm.
But since the purpose of this view is to visualize unpackaged files,
directories that don't contain any packaged files (including completely empty
directories) are also moved to the highest possible `` branch so they
get out of the way.
## Use Cases
### Accumulated Cruft after many Package Updates
Package maintainers are also just humans, and humans make mistakes. Every once
in a while a file that belongs to a package is not listed or listed the wrong
way.
If you have been using a Linux distribution for a long time, you will get many
package updates; using a rolling release like openSUSE Tumbleweed will get you
even more.
After a while, those little packaging bugs may accumulate, and your system may
behave strangely. Some things may stop working or give you very weird error
messages.
Before you nuke your installation completely and reinstall, consider having a
look with this unpackaged files view. You may discover shared libs or symlinks
left behind in crucial system directories like `/usr/lib` or `/usr/lib64`. As a
general rule of thumb, there should be no unpackaged files in those
directories. If you find one, ask in a user forum what they are and why they
might plausibly not be part of a software package.
Or, if you feel brave, move them away (don't delete them right away!) to a
subdirectory, rebuild the linker cache (!) with `ldconfig` and reboot. Make
sure you have some live media (a bootable USB stick or a CD/DVD with a recent
version of the distro you are running) so you can do disaster recovery if
something goes terribly wrong.
**If you don't know what an unpackaged shared lib is that you found, google it
first!**
You may find that it is part of some piece of software that you installed
without using your package manager (some hardware support software comes as a
ZIP file or as a tarball). It might just be part of the crucial driver for that
fancy wireless keyboard or mouse that you use, and using your system without
that hardware may be no fun.
### Recovering from too much make install
This is very similar to the accumulated cruft after many package updates
problem, but it is typically your own fault: When you build software yourself,
it is much easier to install it directly to the system rather than building a
.deb or .rpm package:
```
make && sudo make install
```
If you don't set the install prefix to `/usr/local`, you will end up with
additional or modified files in system directories like `/usr/bin` or
`/usr/lib`. Of course, the package manager doesn't know anything about those
files, so it cannot handle them.
So if you just added a newer version of an important shared lib to your system,
that version may have priority over the system's own version of that lib.
QDirStat's unpackaged files view may help you to identify such files.
Of course it's much better not to get into that kind of trouble in the first
place and install your own custom-built software to a dedicated place like
`/usr/local`, but many users just don't think about that.
### A Useful Tool for Package Maintainers
Maintainers of Linux software packages can use this view to analyze their
packaging work:
- Does the file list contain everything? The packaging tools should complain
if you forget to list anything, but they may also not be perfect.
- Does a package upgrade / uninstall behave properly? Are all files that the
old version installed or created during its life time properly removed? Or is
anything left behind? Do the pre-install / post-install / pre-uninstall /
post-uninstall scripts do the right thing?
### A Useful Tool for Distro QA Engineers and Release Managers
Building and maintaining a Linux distribution is a complex task. There are many
packages involved; a typical Linux installation today has some 2500-4500
packages installed.
Maintaining a software package involves getting the recent sources from
upstream, getting them to build, patching them to integrate well into the
distribution, setting up package dependencies, maintaining the file list and
often enough also writing scripts: pre-install, post-install, pre-uninstall,
post-uninstall.
Upgrading from the old distro version to the new one comes with its own
challenges, in particular if upgrading not only from the last version is
required, but also two or three versions before that.
There is a lot of potential for bugs to sneak in. Multiply that with the number
of packages, and you end up with insane numbers of pitfalls.
So distro QA engineers test at least the most common cases: Upgrade from
release X-1 to X with the standard package set, with the minimal package set,
with the maximum package set; upgrade from release X-2 to X, from X-3 to X.
All those cases should work well with no major problems. Finding leftover files
may contribute to find problems quicker.
### Be Curious! Stay Curious!
What are all those files on my Linux system? Where does all that stuff belong
to?
Remember that QDirStat will show you what package a file belongs to (if any)
when you click on it; the details panel on the right shows the package name.
The package view will show you the complete contents (at least the part that
was installed to your system) in the package view (Menu "File" -> "Show
Installed Packages").
And this view solves the inverse problem: It shows you what files do _not_
belong to any package. Of course that makes most sense for system directories.
If there are unpackaged files in system directories, that may be a bug, or it
may be normal. But it is clearly a starting point for further investigation and
for asking experts.
Linux (and BSD and other Unix-like systems) was meant to be open and easy to
explore. So, become involved. Become knowledgeable what all that stuff on your
system is. You may be able to contribute to finding problems; you don't need to
be a developer for that. Just exploring things and asking the right questions
may help the community as a whole to identify problems.
## Target Platforms
This works on all Linux distributions using one of those low-level package
managers:
- Dpkg
- RPM
- ~~PacMan~~
...and of course all higher-level package managers that are based on any of
them. I.e.
- Debian
- Ubuntu / Kubuntu / Xubuntu / Lubuntu
- SUSE (openSUSE Tumbleweed or Leap, SLES)
- Red Hat (Fedora, RHEL)
- ~~Arch Linux~~
- ~~Manjaro~~
Please notice that _apt_, _synaptic_, _zypper_, _pkgkit_ and whatnot are all
higher level package managers that ultimately use one of the low level ones, so
even if you only use a higher level package manager, it still works without
restriction.
_Sorry, no support for PacMan as of now: There does not appear to be a single
command to generate the complete file list for PacMan. Advanced users can try to use the [script-based version](../scripts/pkg-tools/README.md)._
_If anybody knows a PacMan command to do this, please let me know!_
## Command Line: Unpkg URLs
As an alternative to using the menu, you can also start QDirStat from the
command line with an _unpkg_ URL:
```
qdirstat unpkg:/usr/share
```
This starts the unpackaged files view with `/usr/share` as the starting
directory. It will use the same exclude directories and ignore patterns as the
last time you used that view from the menu.
```
qdirstat unpkg:/
```
This starts the unpackaged files view with the root directory as the starting
directory.
```
qdirstat -d
```
This starts QDirStat without asking for a directory to scan, so you can go
straight to the menu. qdirstat-1.8/doc/cache-file-format.txt 0000664 0000000 0000000 00000016160 14112476455 0020006 0 ustar 00root root 0000000 0000000 The QDirStat Cache File Format
================================
Author: Stefan Hundhammer
Updated: 2016-01-09
QDirStat can read cache files in either gzip or plain text (uncompressed)
format. The file format is line oriented.
Empty lines as well as lines with a '#' character as their first
non-whitespace character are ignored.
To generate a cache file, you can use QDirstat ("File" -> "Write Cache File")
or the supplied qdirstat-cache-writer script in the scripts/ directory of the
QDirStat sources.
Example:
[qdirstat 1.0 cache file]
# Do not edit!
#
# Type path size mtime
D /work/home/sh/kde/kdirstat 159 0x43aea3d3
F ChangeLog 19288 0x43ae9a3b
F .cvsignore 207 0x41c194f3
F stamp-h1 23 0x43ae9d73
F acinclude.m4 357171 0x43ae9d52
F Makefile.am 1237 0x43ad58a0
F config.h 5460 0x43ae9977
D /work/home/sh/kde/kdirstat/kdirstat 549 0x43aea73b
F .cvsignore 108 0x3b7bda58
F kcleanupcollection.cpp 7615 0x41a3322d
F kdirstatapp.cpp 24254 0x43aea372
F kdirtree.cpp 33083 0x43adc843
F kdirstatsettings.cpp 30519 0x3e39540c
F kdirtreeiterators.cpp 7191 0x3e1ad131
F ktreemapview.cpp 17100 0x3f93ee7b
D /work/home/sh/kde/kdirstat/kdirstat/.libs 24 0x43ae9900
D /work/home/sh/kde/kdirstat/kdirstat/.deps 504 0x43aea73a
F ktreemaptile.Po 18074 0x43ae99a0
F kdirtree.Po 18134 0x43aea0ba
D /work/home/sh/kde/kdirstat/kdirstat/pics 144 0x43ae9d72
F hi32-action-symlink.png 1141 0x3c0b5152
F Makefile.am 59 0x41a47537
D /work/home/sh/kde/kdirstat/kdirstat/pics/CVS 64 0x41c194fc
F Entries 447 0x41c194fc
F Repository 23 0x41c194fb
F Root 54 0x41c194fb
D /work/home/sh/kde/kdirstat/kdirstat/CVS 64 0x434657ca
F Entries 2020 0x434657ca
F Repository 18 0x41c194f8
F Root 54 0x41c194f8
(End of example)
Header
======
The first line ( "[qdirstat 1.0 cache file]" ) is a header identifying the file
format. Future versions of QDirStat may or may not check the version number
(the second word of the header line) to make sure the file format is compatible
with that particular version of QDirStat.
For compatibility reasons, QDirStat will recognize both "qdirstat" and
"kdirstat" as file format keywords.
Data Lines
==========
The data lines are separated into fields by whitespace (blanks or tabs).
Fields are not surrounded by single or double quotes.
The maximum line length is 1024 bytes.
Mandatory fields are:
- Type
- Path or name
- Size
- MTime (time of last modification)
After those mandatory fields there may be optional fields in this order:
- "blocks:" followed by a field with the number of blocks
- "links:" followed by a field with the number of links
The identifiers of those optional fields ("blocks:", "links:") are case
insensitive.
Fields
======
Type
----
Any of:
"F" plain file
"D" directory
"L" (symbolic) link
"BlockDev" block device i-node
"CharDev" character device i-node
"FIFO" FIFO (named pipe)
"Socket" socket
The type field is case insensitive.
Path or Name
------------
Either an absolute path (starting with "/") or only a base name relative to
the last preceding full path in the file.
Directory entries are required to have an absolute path. Entries for plain
files, symlinks, or special files (devices, FIFOs, sockets) may have an
absolute or a relative path.
Hint: To save some disk space with relative paths, it makes sense to
list the plain files in a directory first and then descend into any
subdirectories when writing a cache file.
Paths and names are URL-encoded, i.e. any character (in particular whitespace)
that might otherwise be some kind of delimiter is specified as its hex code
with preceding "%":
with blank -> with%20blank
with%percent -> with%25percent
Take special care for blanks, tabs, newlines, and percent characters. It
does not hurt to escape a few more characters than would strictly be
necessary.
As for encoding, unfortunately this is one big mess. 7 bit ASCII works
alright, but if there are any special characters, everything depends on the
locale in which the user created a file. There is no standard for file name
encodings in file systems; special characters may come in all kinds of
flavours - in Latin-1 (ISO-8859-1), Latin-2, UTF-8, Japanese, Korean, Chinese,
whatever. In an ideal world, the file system would take care about this and
normalize file names with non-ASCII (7 bit) characters, but that doesn't
happen. So if one user uses, say, Latin-1 and another uses UTF-8, a file system
may have files with different encodings for each file name. Worse yet, the same
(special, i.e. non-7-bit-ASCII) character will be be stored in different
character representations for different file names.
Those character representations is what readdir() returns. There is no way to
tell in which encoding a name may come, so there is also no way to convert it
to a well-defined standard encoding like, say, UTF-8. So what gets stored in
the cache file is the same byte sequence as returned by readdir(). Those names
encoded in something other than the current locale of KDE where QDirStat is
running will of course be displayed with garbage letters, but this cannot be
helped. This is just the same as when the name is read directly from the file
system with readdir(). Bad luck.
Size
----
The entry's size (st_size in struct stat as returned by lstat() ).
Note: This is the entry's own size, not the accumulated size of all
children!
This size is given in bytes. It may also have a trailing unit (directly
following the number, without whitespace):
- "K" for kB (1024 bytes)
- "M" for MB (1024 kB)
- "G" for GB (1024 MB)
The size is always specified in integer numbers, never in fractional
numbers. So if it cannot be divided by a bigger unit without a fractional
part, use the next-lower unit that fits without fraction.
Examples:
1024 -> 1K
1025 -> 1025 (NOT 1.01K or something like this!)
8589934592 -> 8G
8589934593 -> 8589934593 (bad luck)
MTime
------
The entry's last modification time as time_t, i.e., in seconds since
1970-01-01 00:00:00.
May be specified in hex (with preceding 0x) or decimal.
Blocks
------
If a file is a sparse file (and only then) it has a "blocks:" field.
This is the content of the st_blocks field of struct stat as returned by
lstat(): The number of disk blocks actually allocated.
This number multiplied by the block size may be less than what st_size
returns; in this case that file is considered to be a "sparse" file or a
file with "holes".
A block size of 512 bytes is assumed.
Example:
blocks: 17
This file has 17*512 bytes allocated.
Links
-----
If a non-directory entry has more than one hard link, the entry has a
"links:" field indicating the number of hard links:
links: 7
qdirstat-1.8/doc/doc.pro 0000664 0000000 0000000 00000000715 14112476455 0015265 0 ustar 00root root 0000000 0000000 # qmake .pro file for qdirstat/doc
isEmpty(INSTALL_PREFIX):INSTALL_PREFIX = /usr
TEMPLATE = app
TARGET = $(nothing)
doc.files = *.txt *.md ../*.md
# Ubuntu / Debian pkg doc path
doc.path = $$INSTALL_PREFIX/share/doc/qdirstat
exists( /usr/share/doc/packages ) {
# SUSE pkg doc path
doc.path = $$INSTALL_PREFIX/share/doc/packages/qdirstat
# SUSE wants the license installed for each package
doc.files += ../LICENSE
}
INSTALLS += doc
qdirstat-1.8/doc/stats/ 0000775 0000000 0000000 00000000000 14112476455 0015131 5 ustar 00root root 0000000 0000000 qdirstat-1.8/doc/stats/Buckets-Table.md 0000664 0000000 0000000 00000003213 14112476455 0020077 0 ustar 00root root 0000000 0000000 # The Buckets Table

This shows the _buckets_ of the histogram as a table. It is the same
information you can get when hovering over the histogram bars.
For a histogram, files are put into _buckets_, i.e. they are classified by
their size: Files of similar sizes are put into the same bucket, and the
histogram shows how many files there are in each bucket.
Columns from left to right:
- Bucket number. How many buckets there are depends on the number of data
points, i.e. the total number of files. QDirStat uses the
[Rice Rule](https://en.wikipedia.org/wiki/Histogram#Rice_Rule)
to determine the number of buckets so there is a reasonable number of data
elements in each bucket. If there are too many buckets, many of them won't
have any data, and the others will have very similar numbers, so it would be
hard to make any sense of the histogram.
QDirStat uses a maximum of 100 buckets so each bucket is still wide enough to
be well visible and clickable.
- The start value of the bucket, i.e. the minimum file size for a file to be
put into that bucket.
- The end value of the bucket, i.e. the maximum file size for a file to be put
into that bucket. The end value of this bucket is also the start value for
the next one.
- The number of files in that bucket. This is what the histogram displays.
------------------------
## Navigation
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/File-Size-Histogram.md 0000664 0000000 0000000 00000016337 14112476455 0021207 0 ustar 00root root 0000000 0000000 # QDirStat's File Size Histogram
_This explains the histogram itself. The overflow ("cut off") area is described in a
[separate document](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Overflow-Area.md),
and the histogram options in
[yet another separate document](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histogram-Options.md)._

## How to Get this Window
1. In QDirStat's tree view, select a directory, then menu _View_ ->
_File Size Statistics_ or hit the F2 key.
2. In QDirStat's _File Type Statistics_, open a file type category, then select
a filename suffix (e.g. `*.jpg`), then open the _File Type_ menu button and
select _Size Statistics_ or hit the F2 key.

_Histogram showing only .jpg files in that directory_
## Histogram Panel Content
This histogram displays the distribution of file sizes in the selected
directory (see window heading). If a filename suffix ("*.jpg" or similar) is
displayed, it is restricted to files of that type.
### The Colored Heading Values
From left to right, you see
- The first quartile (Q1) of the file sizes
- The median of the file sizes
- The third quartile (Q3) of the file sizes
- The total number of files in the histogram, i.e. the sum of all bucket
values.
If the terms _median_, _quartile_, _percentile_ don't mean anything to you, you
might want to read the
[intro document where they are explained](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md).
### The Histogram
The horizontal (x) axis shows the file sizes, the vertical axis the bucket
values, i.e. the number of files in each bucket (in each size interval).
The vertical axis might be linear (if labeled just with **n**) or logarithmic
(if labeled with **log2(n)**) with a base 2 logarithm.

_Histogram with logarithmic scale_
The same principle still applies: The higher a bar, the more files are in a
bucket. But it's no longer a linear relationship between the bars; a bar that
is just slightly higher might have double the data points if a logarithmic
scale is used. Use tooltips to find out the true numbers.
### What is it Good For?
- You can see the vast amount of very small files on a Linux system.
- You can see the sizes of your MP3s, of your videos, of your photos and maybe
make educated decisions about them.
- You might use that information for optimizations for very special servers.
Back a long time ago, news servers were notorious for creating a large number
of very small files. Some http servers might be similar. Some database
servers might be completely different.
- Filesystem developers might find that information useful for optimizing or
fine-tuning parameters.
- You might want to compare the data from your Windows partition to your Linux
partition. You **will** notice differences.
- You might be just curious.
- Information is power. Use your imagination what to do with it.
### Tooltips
You can get a tooltip for each histogram item (bars or percentile marker) if
you hover the mouse over it. Sometimes you might have to click into the window
first so it gets focus.
A tooltip looks like this:
Bucket #20:
707 Files
1.6 MB .. 1.7 MB
You can get the same information for all buckets at once by switching to the
_Buckets_ page in that dialog.
### The Markers
Markers for Q1, the median and Q3 are superimposed over the histogram: They are
the colored vertical lines. Their respective color is the same as in the
heading above the histogram.
At the right, there are some more grey markers; they show some percentiles at
the border of the histogram. They are useful to get an idea how much the
percentiles are spaced out in that area. Typically, the last few percentiles
are very wide, i.e. the data points in that area are very widely spaced. You
could say "the air gets thinner" the more you get away from the center part.
### Histogram Boundaries
It is very common for file sizes on a real life filesystem to be vastly
different: You might have a large number of tiny files, and you might also have
a couple of ISOs or videos of 2 GB each. Put into the same histogram, this
looks like this:

This histogram does not really give away any useful information: You can see
that the vast majority of files is at the left side, and then there are wide
stretches of file sizes that don't appear anywhere in that directory tree
(where all the gaps are), and then there are some very large files in the 2.5
GB area. This is not very useful.
This is why QDirStat by default uses some heuristics to determine useful
boundaries for the histogram: It uses the _interquartile distance_ (Q3 - Q1)
and adds some generous distance to the left and to the right of Q1 and Q3:
leftBoundary = Q1 - 3 * (Q3 - Q1)
rightBoundary = Q3 + 3 * (Q3 - Q1)
(maxed out at minValue (P0) and maxValue (P100), of course)
But in our extreme example (which is actually quite common), even if we leave
just one percentile out and display the histogram from P0 to P99, it becomes
much more useful:

As you can see, the right boundary is still at 10.7 MB, and the "interesting"
area between Q1 and Q3 is still pretty much crammed together at the left, but
now at least we can make some sense of it all (notice that it's using a
logarithmic vertical scale, so it's not nearly as evenly distributed as you
might think).
Percentile data for reference:

### Why Not Use a Logarithmic Scale There, Too?
This is a tempting idea, but it would make the histogram display either
incorrect or very difficult to interpret: By definition, the area of each bar
corresponds to its numeric value (to the number of files in that bucket).
By using a logarithmic scale there, too, the width (!) of the bars would have
to get logarithmic, too: This would mean very fat bars on the left and very
thin bars on the right. If there are extreme differences like in this example,
the right bars would degenerate into thin lines, and even that would be
technically wrong because they would need to have sub-pixel widths. Remember
that we are comparing ranges of some few bytes with gigabytes; that's a factor
1024\*1024\*1024 difference. It's just not feasible to display that.
So the more pragmatic approach is to cut off at a sensible limit.
----------------------------------
## Navigation
[Next: The Overflow Area](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Overflow-Area.md)
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/Histogram-Options.md 0000664 0000000 0000000 00000003444 14112476455 0021046 0 ustar 00root root 0000000 0000000 # Histogram Options in QDirStat's File Size Histogram
When you click on the `Options >>` button below the histogram, some
interactive controls become visible:

Here you can change the left and right boundary of the histogram.
Typically, the left boundary is P0 (percentile #0, the minimum file size), but
the right boundary is below P100 (percentile #100, the maximum file size).
As explained in the
[file size histogram article](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/File-Size-Histogram.md),
QDirStat automatically determines a useful values for both boundaries.
But that's just heuristics, and the value might not always be the optimal
one. So here you have the tool to experiment with better values: Use the
sliders or the _spin boxes_ below them to change the start and end percentile.
Notice you can't cut off above Q1 or below Q3: That part of the histogram will
always remain visible.
If you set the end percentile to P100, the overflow ("Cut off") panel will
disappear. This is normal and intentional since in that situation nothing is
cut off.
The _Auto_ button resets both to the automatically calculated values:
leftBoundary = Q1 - 3 * (Q3 - Q1)
rightBoundary = Q3 + 3 * (Q3 - Q1)
(maxed out at minValue (P0) and maxValue (P100), of course)
Hit `<< Options` again to close the histogram controls.
------------------------------
## Navigation
[Next: The Percentiles Table](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Percentiles-Table.md)
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/Histograms-in-General.md 0000664 0000000 0000000 00000011564 14112476455 0021561 0 ustar 00root root 0000000 0000000 # Histograms in General
(c) 2017 Stefan Hundhammer
License: GNU Free Documentation License
## Quick Overview
A histogram is a graphical representation of data: The data are grouped into
_buckets_ (or _bins_) of intervals (usually of equal width), and bars are drawn
to show how many data points fall into each bucket. The higher the bar, the
more data are in a bucket.
From the resulting graphics you can easily see if data points are concentrated
in any area, if there are any peaks, and how data are distributed.
## Detailed Explanation
### Number of Buckets
First you need to determine the number of buckets to use.
This is not anything as easy as it may sound: Too many buckets, and you will
end up with many buckets without any data, leaving gaps in the graphics; and at
the same time the buckets that do have data will have very few of them which
makes any comparison between them difficult.
If you have too few buckets, it is very likely that many data will be
concentrated in very few of them, which leaves you with the bars for those few
buckets being huge in comparison with the others. Again, it makes analysis of
the resulting histogram very difficult.
There are a number of formulas to calculate a reasonable number of
buckets. QDirStat uses the
[Rice Rule](https://en.wikipedia.org/wiki/Histogram#Rice_Rule).
It uses a maximum of 100 buckets so the resulting histogram bars don't
degenerate to very thin lines, but remain well visible and also clickable.
### Buckets vs. Percentiles
All buckets have the same width, while percentiles typically have very
different widths. Each percentile interval (the interval between a percentile
and the previous one) always has the same number of data points (by definition,
each of them has 1/100 of the data points).
### Histogram Bars
Each histogram bar corresponds to one bucket. In normal histograms, the height
of each bar shows the number of data points in the bucket.
_There are also histograms where the buckets have different widths; in that
case, it is not the height, but the area of the histogram bar that corresponds
to the number of data points. But that is hard to interpret, so that kind of
histogram shall be disregarded here._
Notice that unlike with bar graphs, there are no gaps between histogram bars:
This is because of the way the buckets are defined. The end point of one bucket
is also the start point of the next bucket; this is how each possible data
point can be unambiguously put into one bucket.
If you see any gaps in a histogram, you are seeing an empty bucket (or possibly
multiple empty buckets).
### Method
Scenario:
We measured 1000 data points. The minimum measured value is 100, the maximum
200.
According to the Rice Rule, we need `2 * 1000^(1/3) = 20` buckets.
The range we need to display is `max - min = 200 - 100 = 100`.
The bucket width is `range / bucketCount = 100 / 20 = 5`.
So we get those buckets:
| Bucket # | Start | End |
| -------: | ----: | --: |
| 1 | 100 | 105 |
| 2 | 105 | 110 |
| 3 | 110 | 115 |
| 4 | 115 | 120 |
| .. | ... | ... |
| .. | ... | ... |
| 18 | 185 | 190 |
| 19 | 190 | 195 |
| 20 | 195 | 200 |
How to handle the boundaries for its bucket is open to definition. A
practicable definition would be to check for `start <= x < end`.
Then we go through all data and determine the bucket where each data point
belongs. For that bucket, we increment its counter by one.
| Data Value | Bucket # |
| ---------: | -------: |
| 118 | 4 |
| 187 | 18 |
| 101 | 1 |
| 119 | 4 |
| ... | ... |
| ... | ... |
Notice that the data don't need to be sorted for that.
Finally, we determine the maximum counter of all buckets; this is the maximum
for the vertical scale. Then we can begin drawing the histogram bars.
##
###
######
######### ##
############ ####
#####################
---------------------
1 5 10 15 20
Bucket No. --->
In this example, we have two clearly defined peaks: One around bucket #9, and
another one around bucket #17.
Notice how the histogram shows information even without knowing anything about
the vertical scale; just the relative sizes of the bars against each other are
enough. It does help, though, to mark the horizontal (x) axis to get any idea
where the peaks or valleys are.
## Reference
https://en.wikipedia.org/wiki/Histogram
(Much better readable than the Wikipedia article about percentiles)
----------------------------------
## Navigation
[Next: The File Size Histogram](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/File-Size-Histogram.md)
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/Median-Percentiles.md 0000664 0000000 0000000 00000023407 14112476455 0021131 0 ustar 00root root 0000000 0000000 # Median, Quartiles and Percentiles Explained
(c) 2017 Stefan Hundhammer
License: GNU Free Documentation License
## Motivation
_"Do not trust any statistics you did not fake yourself."_
(Joseph Goebbels, often wrongly attributed to Winston Churchill)
This is the instant reply some moron will ALWAYS bring up whenever anybody
begins talking about statistics, thus instantly discrediting whatever facts
were brought up.
But all that does is to make any intelligent discussion (that is, any
fact-based discussion) virtually impossible, replacing hard facts with mere
sentiments. While there might be some virtue to something meteorologists call
"perceived temperature" (because it takes the wind chill factor into account),
"perceived facts" are completely worthless. Yet they seem to rule the day in a
society where it is considered chic to state "I've always been bad at math"
(and nobody replies "you should be ashamed of yourself").
But important decisions should be based on facts, not on feelings. That's where
statistics come into play; and that's when average people feel overwhelmed
rather than informed. What is all that stuff? Everybody knows what an average
value is, but what is a median, what are percentiles? And who cares anyway?
It's actually very simple. It doesn't take a math genius to understand; every
average (here we go again!) person can do that. Just read on.
## The Farmers of Dairyville
Dairyville is a fictional village with a number of farmers; some small ones
with only very few cows, most with a pretty medium-sized number, and there is
also that big large corporation Agricorp, Inc. with a lot of cows:
#1 Collins 1 cow
#2 Myers 2 cows
#3 Davis 12 cows
#4 Thompson 12 cows
#5 Fletcher 14 cows
#6 Allen 15 cows
#7 Brown 16 cows
#8 Eliott 16 cows
#9 Robinson 17 cows
#10 Jones 18 cows
#11 Simpson 38 cows
#12 Agricorp, Inc. 400 cows
Total 561 cows
The average is 561 / 12 = 46.75.
But that does not describe any of the farmers well; worse, that average is a
meaningless number: It does not fit any of the normal farmers, much less the
big Agricorp, Inc. corporation.
Why this is so is obvious in this case: That big Agricorp, Inc. is greatly
distorting the result. There must be a better way to do this; one that actually
makes a meaningful statement about the typical farmer of Dairyville.
Well, there is. It is called the median.
## The Median
The median is a value determined by putting all the data in a sorted list and
then choosing the middle point. It is the point where as many data points are
below as there are above.
#1 Collins 1 cow
#2 Myers 2 cows
#3 Davis 12 cows
#4 Thompson 12 cows
#5 Fletcher 14 cows
#6 Allen 15 cows
------------------------------ Median
#7 Brown 16 cows
#8 Eliott 16 cows
#9 Robinson 17 cows
#10 Jones 18 cows
#11 Simpson 38 cows
#12 Agricorp, Inc. 400 cows
In our example the data are already conveniently sorted and numbered, so we
just have to pick the middle point from the 12 data points: Between #6 and #7,
i.e. between farmer Allen and farmer Brown, between 15 and 16 cows, i.e. 15.5
cows.
If you look at the data, that is a much more accurate description of the
typical Dairyville farmer.
Better yet, if you were to take Agricorp out of the calculation, you'd end up
with a very similar number: Then the median would be at #6, farmer Allen, with
15 cows. No big change (from the previous 15.5).
On the other hand, the average would change from 46.75 to 14.63 - quite a
drastic change.
If you were to disregard the very small farms #1 and #2, the median would be
16, no matter if Agricorp were still in the table or not.
The median is a very useful measure; it is very stable against weird "outliers"
(outlying data points very far from the center), unlike the average.
This is why the median is typically used for professional statistics of any
kind; never again let anyone fool you into believing that "the average income
in our country is only so high because of a few billionaires who greatly
distort the statistics". That is a flat-out lie. The pros use the median, and
the billionaires don't make a difference at all.
If you watch closely, the pros always talk about the "median household income",
never about the "average household income" because that would indeed be a
meaningless number. It's just the media who tend to misquote it and change it
from "median" to "average" because they think that makes it easier to
understand.
## Quartiles
The concept goes further. Now that we know what the median is, can we make any
more meaningful statements about the typical Dairyville farmer?
We can. Let's just cut the list in half at the median and apply the same
principle again:
Lower half:
#1 Collins 1 cow
#2 Myers 2 cows
#3 Davis 12 cows
----------------------------- 1st Quartile
#4 Thompson 12 cows
#5 Fletcher 14 cows
#6 Allen 15 cows
Upper half:
#1 Brown 16 cows
#2 Eliott 16 cows
#3 Robinson 17 cows
----------------------------- 3rd Quartile
#4 Jones 18 cows
#5 Simpson 38 cows
#6 Agricorp, Inc. 400 cows
Voila, we just cut our farmer population into quarters.
The dividing points (the medians of the lower and upper halves) are called the
"first quartile" and the "third quartile". The second quartile technically
exists, but it is much better known for its other name: The median.
In more advanced statistics, the segment between the 1st quartile (Q1) and the
3rd quartile (Q3) is considered the most important part of the data. The value
difference between them is called the "interquartile distance"; in our example,
this would be 17.5 - 12 = 7.5.
This is an important number for a lot of things, such as deciding where and how
to leave out data in certain types of graphical representations such as "box
plots": They typically cut off outlying data points beyond 1.5 * (Q3-Q1) on
either side so the graphics remain meaningful.
In our example, that would mean to cut off below Q1 - 1.5 * 7.5 = 0.75 and
above Q3 + 1.5 * 7.5 = 28.
That would mean that farmer Collins would still be in the graph, but Agricorp
and farmer Simpson would not.
## n-Quantiles, Deciles and Percentiles
In a mathematical sense, the concept is easy to generalize; it is called
"n-quantiles" where "n" is the number of segments after the division.
So, the median would be the 2-quantile, the quartiles would be 4-quantiles.
When used with n = 10, they are called "deciles"; with n = 100, they are called
"percentiles". And the percentiles are the most useful and come most natural to
us modern people who are used to think in terms of percent.
Dairyville has not enough farms to come up with a useful percentile table; with
a full one, that is.
But just think about it: The median is the middle point of the percentiles,
i.e. the 50th percentile (P50); the first quartile is the 25th percentile
(P25), the third quartile the 75th percentile (P75):
#1 Collins 1 cow
#2 Myers 2 cows
#3 Davis 12 cows
------------------------------ P25 (Q1)
#4 Thompson 12 cows
#5 Fletcher 14 cows
#6 Allen 15 cows
------------------------------ P50 (Median)
#7 Brown 16 cows
#8 Eliott 16 cows
#9 Robinson 17 cows
------------------------------ P75 (Q3)
#10 Jones 18 cows
#11 Simpson 38 cows
#12 Agricorp, Inc. 400 cows
Notice that strictly speaking, there is no P100, and no P0. But it is useful to
extend the concept a little further, and define P100 the maximum of the data
and P0 the minimum, so the percentiles (even if only very few of them can be
calculated with only 12 data points) can serve to completely describe the data
set:
------------------------------ P0 (Min)
#1 Collins 1 cow
#2 Myers 2 cows
#3 Davis 12 cows
------------------------------ P25 (Q1)
#4 Thompson 12 cows
#5 Fletcher 14 cows
#6 Allen 15 cows
------------------------------ P50 (Median)
#7 Brown 16 cows
#8 Eliott 16 cows
#9 Robinson 17 cows
------------------------------ P75 (Q3)
#10 Jones 18 cows
#11 Simpson 38 cows
#12 Agricorp, Inc. 400 cows
------------------------------ P100 (Max)
**Notice:** The percentiles/quartiles/median are the **dividing points**, not
the interval at either of their sides.
## Further Reading
Read the full description that is no doubt mathematically correct, but utterly
incomprehensible and thus useless to the normal human here:
https://en.wikipedia.org/wiki/Quantile
https://en.wikipedia.org/wiki/Median
https://en.wikipedia.org/wiki/Quartile
(This bunch of uselessness is why I wrote this document)
## Disclaimer
No animals (or farmers) were harmed in the making of this.
We'd like to thank the farmers and cows of Dairyville and the Dairyville
chamber of commerce for their kind cooperation.
;-)
## Navigation
[Next: Histograms in General](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histograms-in-General.md)
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/Overflow-Area.md 0000664 0000000 0000000 00000011601 14112476455 0020123 0 ustar 00root root 0000000 0000000 # The Overflow Area in QDirStat's File Size Histogram
Since QDirStat in most cases does not display the full data range, but rather
cuts off at a sensible point, it displays a special panel next to the histogram
when it does that as a reminder that you are not seeing the complete data set.

In the above case, it's pretty harmless: The overflow ("Cut off") panel shows
that a small part of the data was cut off: Percentile P98 to P100.
Remember that each percentile contains by definition 1/100 of all data points
(in this case: of all files), so in this case it's just 1% of all data points
that were cut off; in this example, 647 files. But the histogram still shows
the remaining 97%, 31732 files total (this is the rightmost / black value above
the histogram).
The upper pie chart shows that information graphically. It's no big deal,
really.
But P98..P100 in this case means cutting off from 5.3 MB to 31.1 MB, so it's a
really wide part of the x axis that gets cut off; to show that all, it would
need to be more than 6 times as wide. If scaled to the same window width, that
would mean that the meaningful part of the histogram would only be 1/6 of the
total width with vast areas of emptiness to its right. That's _why_ that part
was cut off.
But even though it's only 2% of all files, those files together account for
14.3% of the disk space in that directory tree: 7.4 GB total. This is what the
lower pie chart shows. Again, this is not really significant, much less for the
purpose of file size distribution which this window is all about. But it's a
reminder not to just disregard those few files - because they are **big**.
## A More Extreme Example
_Oh PacMan, where art thou?_
_...and why art thou red?_

Going one directory level up, we get this histogram, and this is an entirely
different matter:
The heuristics for determining the histogram boundaries decided on displaying
P0 to P86. This does make sense in order to have the most important part of the
distribution between Q1 (P25) and Q3 (P75) in view.
But on the other hand, it cuts off 14% of all files (14 percentiles), the range
between 1.6 MB and 2.5 GB. That's three magnitudes (1024) of difference in file
size. The red slice of the upper pie chart is considerably bigger than in the
previous example.
For the accumulated size of those files that were cut off, it means that they
now contribute to 92.0% of the total disk space in that directory tree (the red
part of the pie charts is always the part that is cut off), by far dwarfing the
accumulated sizes of those files that are displayed in the histogram.
Again, this may or may not bother you; it depends on what information exactly
you are looking for in the histogram. But this is where you might want to
decide to show just a little more of the data range by opening the histogram
options and moving the sliders.
Moving the _End Percentile_ slider to P99 in this case gets you this:

OK, that did put things a bit more into proportion - at the price that the most
important part of the data, Q1 .. Q3, has now become a lot less visible: It now
has 1/4 of its previous display size (since the right boundary is now at 10.7 MB
from the previous 1.6 MB).
Still, the remaining 1% of the files that were cut off contribute to 64.7% of
the total disk space: The red slice is still the dominant one, albeit no longer
quite as much as before. _PacMan opened its mouth for us._ ;-)
But going full hog and moving the _End Percentile_ slider all the way to P100
is not helpful, either:

Duh. There is no longer an overflow panel since now nothing is cut off, but the
histogram is pretty worthless: We can now see that there are some files in the
2.5 GB range, but the core of the histogram (Q1..Q3) has now degenerated to
some 5 pixels wide with colored lines. All we can see in this histogram is that
there is a lot of little stuff on the left, then it peters out for a wide
stretch, and there is another peak on the right. Notice, though, that due to
the logarithmic vertical scale that peak is not nearly as high as it appears:
It's just 18 files (!) in comparison to bucket #1 (the peak at the very left)
with 98206 files.
-----------------------------
## Navigation
[Next: Histogram Options](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histogram-Options.md)
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/Percentiles-Table.md 0000664 0000000 0000000 00000004247 14112476455 0020764 0 ustar 00root root 0000000 0000000 # The Percentiles Table

This table shows the percentiles of the file size statistics.
If you don't know what percentiles are, please read the
[percentiles documentation](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md)
first.
Columns from left to right:
- Percentile number (P0 .. P100).
- Percentile value. This is the file size where that percentile is. Remember
that percentiles are the dividing point, not an interval. Percentile P10 is
the point where 10% of all data points are below, 90% are above.
- The name of the percentile if there is any special name:
| Percentile | Name |
|------------|------------------|
| P0 | Min |
| P25 | 1. Quartile (Q1) |
| P50 | Median |
| P75 | 3. Quartile (Q3) |
| P100 | Max |
- The accumulated sum of all data points (of all files) between the the
previous percentile and this one.
If you wonder how many data points (files) fall into any interval between the
previous percentile and this one: That's always 1/100 of the total number of
data points (files). This is why this is not listed in the table; that would be
the same number for each percentile.
This table shows either all or only the interesting percentiles. Use the combo
box at the top right to switch between those two views.
Interesting percentiles in the context of this table are those with a special
name (see above), those with a number that can be divided (without remainder)
by 5, and a few around the extremes (min and max).

_Full percentiles table_
----------------------------
## Navigation
[Next: The Buckets Table](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Buckets-Table.md)
[Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md)
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/README.md 0000777 0000000 0000000 00000000000 14112476455 0021057 2Statistics.md ustar 00root root 0000000 0000000 qdirstat-1.8/doc/stats/Statistics.md 0000664 0000000 0000000 00000002031 14112476455 0017601 0 ustar 00root root 0000000 0000000 # Statistics in QDirStat
## Statistics Basics
### Median, Quartiles and Percentiles Explained
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md
### Histograms in General
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histograms-in-General.md
-----------------------------
## QDirStat File Size Statistics
### The File Size Histogram
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/File-Size-Histogram.md
### The Overflow Area
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Overflow-Area.md
### Histogram Options
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histogram-Options.md
### The Percentiles Table
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Percentiles-Table.md
### The Buckets Table
https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Buckets-Table.md
----------------------------------
## Navigation
[Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md)
qdirstat-1.8/doc/stats/stats.pro 0000664 0000000 0000000 00000000603 14112476455 0017010 0 ustar 00root root 0000000 0000000 # qmake .pro file for qdirstat/doc/stats
isEmpty(INSTALL_PREFIX):INSTALL_PREFIX = /usr
TEMPLATE = app
TARGET = $(nothing)
doc.files = *.txt *.md
# Ubuntu / Debian pkg doc path
doc.path = $$INSTALL_PREFIX/share/doc/qdirstat/stats
exists( /usr/share/doc/packages ) {
# SUSE pkg doc path
doc.path = $$INSTALL_PREFIX/share/doc/packages/qdirstat/stats
}
INSTALLS += doc
qdirstat-1.8/man/ 0000775 0000000 0000000 00000000000 14112476455 0014001 5 ustar 00root root 0000000 0000000 qdirstat-1.8/man/.gitignore 0000664 0000000 0000000 00000000010 14112476455 0015760 0 ustar 00root root 0000000 0000000 *.1.gz
qdirstat-1.8/man/man.pro 0000664 0000000 0000000 00000001346 14112476455 0015302 0 ustar 00root root 0000000 0000000 # qmake .pro file for qdirstat/man
isEmpty(INSTALL_PREFIX):INSTALL_PREFIX = /usr
TEMPLATE = aux
TARGET = man
MAN_SRC = qdirstat.1 \
qdirstat-cache-writer.1
MAN_TARGET = qdirstat.1.gz \
qdirstat-cache-writer.1.gz
MAN_PATH = $$INSTALL_PREFIX/share/man/man1
man.files = $$MAN_TARGET
man.path = $$MAN_PATH
man.extra = \
gzip --keep --force $$MAN_SRC; \
install $$MAN_TARGET $(INSTALL_ROOT)$$MAN_PATH
# The INSTALL_ROOT environment variable is used for rpm builds in the spec file
# to allow for a build root that is separate from the system directories:
#
# make install INSTALL_ROOT=%{buildroot}
INSTALLS += man
QMAKE_CLEAN += $$MAN_TARGET
qdirstat-1.8/man/qdirstat-cache-writer.1 0000664 0000000 0000000 00000003264 14112476455 0020276 0 ustar 00root root 0000000 0000000 .TH QDIRSTAT-CACHE-WRITER "1" "July 2017"
.SH NAME
qdirstat\-cache\-writer \- script to write QDirStat cache files from cron jobs
.SH "Usage:"
\fI\,qdirstat\-cache\-writer\/\fP [\-ldvh] []
.IP
If not specified, defaults to ".qdirstat.cache.gz"
in .
.IP
If ends with ".gz", it will be compressed with gzip.
qdirstat can read gzipped and plain text cache files.
.TP
\fB\-l\fR
long format \- always add full path, even for plain files
.TP
\fB\-m\fR
scan mounted file systems (cross file system boundaries)
.TP
\fB\-v\fR
verbose
.TP
\fB\-d\fR
debug
.TP
\fB\-h\fR
help (this usage message)
.PP
QDirStat can read its information from cache files. This is a lot faster than
reading all the directories in a directory tree and obtaining detailed
information (size, type, last modification time) for each file and directory
with the opendir() / readdir() and lstat() system calls for each individual
file and directory.
.PP
QDirStat can also write those cache files ("Write Cache File..." from the
"File" menu), but the whole point of cache files is being able to do that in
the background when the user does not have to wait for it \- like in a cron
job running in the middle of the night. QDirStat itself cannot be used to do
that because it is a KDE program and thus an X program that needs access to
an X display \- which cron does not provide.
.SH "AUTHOR"
This manual page was written by Patrick Matth\[:a]i
for qdirstat.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU General Public License, Version 2 any
later version published by the Free Software Foundation.
qdirstat-1.8/man/qdirstat.1 0000664 0000000 0000000 00000017063 14112476455 0015725 0 ustar 00root root 0000000 0000000 .TH "QDirStat" "1" "July 2019"
.SH NAME
QDirStat \- Qt\-based directory statistics
.SH DESCRIPTION
QDirStat is a graphical application to show where your disk space has gone and
to help you to clean it up.
.SH USAGE
.B qdirstat
[OPTION]...
[\fI\fR]
.B qdirstat
\-\-cache|\-c \fI\fR
.B qdirstat
pkg:/\fI\fR
.B qdirstat
unpkg:/\fI\fR
.SH OPTIONS
.PP
.B \-h|\-\-help
.IP
Show a summary of command line options on stdout.
.B That information might be more up-to-date than this man page.
.PP
.B \-s|\-\-slow\-update
.IP
Slow down display updates during directory reading. This is useful when running
QDirStat over a remote X11 connection.
The exact update interval is specified in the \fBSlowUpdateMillisec\fR
parameter in the \fB[DirectoryTree]\fR section of the configuration file. The
default is 3000 milliseconds (3 seconds).
.PP
.B \-d|\-\-dont-ask
.IP
Don't prompt for a directory to read upon program start even if no directory
was specified on the command line.
.PP
.B \-c|\-\-cache \fI\fR
.IP
Read the content of a directory tree from a \fIcache file\fR that was generated
by QDirStat's "Write to Cache File" option or by the \fBqdirstat-cache-writer\fR
script.
A file \fB.qdirstat.cache.gz\fR in the directory that it describes is
automatically picked up and used: A cache file
/data/archive/foo/.qdirstat.cache.gz with the content of /data/archive/foo is
used automatically when found while reading a directory tree containing it.
.SH NORMAL OPERATION
.PP
You start the program without any parameters; then it will open a directory
selection box to let you choose an existing directory. Alternatively, you can
specify the path of an existing directory as a command line parameter.
The program will then start reading that directory tree, i.e. it will
recursively traverse that directory tree and read information for each
directory and its subdirectories.
The result is displayed in a tree view where you can open and close
branches. The tree view displays information such as the accumulated size of
each subtree, the number of items, the number of files, the latest modification
time ("mtime") in that subtree, and some more. You can sort the tree by each of
those columns.
You can select one or more items in the tree view to get more detailed
information or to start "cleanup actions": Move to trash, remove immediately
(caution!), create a gzipped tarball from a directory, "make clean", open a
file manager window with that directory or start a shell there - and more. Use
the context menu (right mouse button) or the "Clean Up" menu in the menu bar
(you can "tear off" that menu so it remains open).
There are three predefined column layouts L1, L2, L3 where you can switch what
columns are displayed and whether or not to display the details panel at the
right.
Right-click on a column header to show or hide individual columns or to switch
between automatic column width and a user-defined width (drag the column
divider in the header). You can rearrange the order of columns with drag and
drop (but the "Name" column will always remain fixed at the very left side).
.SH THE TREEMAP
As a secondary view, there is a "treemap" with colored rectangles
("tiles"). The area of each of those tiles corresponds to its size; the larger
a tile, the larger the item. So you can spot a large file buried deep down in
the directory hierarchy easily.
The color of each tile corresponds to its type ("MIME category"). There are
number of predefined categories such as images (photos etc.), videos, music
etc.; they can be configured in the configuration dialog (menu "Edit" ->
"Configure QDirStat").
.SH PKG URLS / PACKAGES VIEW
.PP
Specifying a \fBpkg:/\fR URL at the command line starts the packages view that
groups files by the software package they belong to.
The package specification in the pkg:/ URL is case insensitive.
Some heuristics are used to determine what mode to use: The default is "starts
with", but if the search pattern contains typical regexp special characters, it
interprets the pattern as a regular expression.
If it detects just "*" (not ".*") or "?", it uses wildcard mode.
If the first character is "=", it uses exact matching.
.PP
\fBqdirstat pkg:/chrom\fR
.IP
This shows all packages starting with "chrom" or "Chrom" or "CHROM".
.PP
\fBqdirstat pkg:/=emacs\fR
.IP
This shows only package "emacs", not "emacs25" or any other one starting with
"emacs".
.PP
\fBqdirstat "pkg:/*gtk*"\fR
.IP
This shows all packages that have "gtk" somewhere in their name.
Notice that you have to protect the "*" wildcards from the shell by escaping
them with quotes.
.PP
\fBqdirstat "pkg:/.*qt[45].*"\fR
.IP
This shows all Qt4 or Qt5 packages.
.PP
\fBqdirstat "pkg:/(firefox|mozilla|chrome|chromium|opera)"\fR
.IP
This shows all the well-known browsers on the system. Notice that regular
expressions use a partial match, so use the "^" and "$" anchors when appropriate.
.SH UNPKG URLS / UNPACKAGED FILES VIEW
.PP
Specifying an \fBunpkg:/\fR URL at the command line starts the "unpackaged
files" view: This reads the specified directory and ignores files that are
owned by an installed software package.
.PP
Some well-known directories that are known to contain only unpackaged files are
excluded by default, and some file types are ignored by default:
.IP
.TS
tab(@);
l l .
/home@user home directories
/root@home directory of the root user
/tmp@directory for temporary files
/var@variable data for all kinds of software
/usr/lib/sysimage/rpm@RPM database
/usr/local@locally installed software
*.pyc@compiled Python files
.TE
.PP
This list can be modified when starting the unpackaged files view from the
menu. Starting the view from the command line uses the same settings that were
used last time when using the menu.
.PP
\fBqdirstat unpkg:/\fR
.IP
This shows the unpackaged files of the complete root filesystem.
.PP
\fBqdirstat unpkg:/usr/share\fR
.IP
This shows the unpackaged files of /usr/share.
.SH FILES
.TS
tab(@);
l l .
~/.config/QDirStat/QDirStat-cleanup.conf@cleanup actions configuration
~/.config/QDirStat/QDirStat-exclude.conf@exclude rules configuration
~/.config/QDirStat/QDirStat-mime.conf@MIME categories configuration
~/.config/QDirStat/QDirStat.conf@general configuration
/tmp/qdirstat-$USER/qdirstat.log@current / last log file
/tmp/qdirstat-$USER/qdirstat-*.old@previous log files
**/.qdirstat.cache.gz@auto-used cache file
.TE
It is safe to delete any or all of the configuration files; the next program
start will restore them with default settings.
The configuration files can safely be edited while QDirStat is not
running. Many parameters can be accessed via GUI, but some (the more arcane
ones) can only be changed by editing a configuration file manually.
.SH PROJECT HOME PAGE
.UR
https://github.com/shundhammer/qdirstat
.SH SEE ALSO
.UR
https://github.com/shundhammer/qdirstat/tree/master/doc
and don't forget the "Help" menu!
.SH BUGS
See the issue tracker at the project repository:
.UR
https://github.com/shundhammer/qdirstat/issues
.PP
.SH AUTHORS
QDirStat was written by Stefan Hundhammer based on
the original KDE 3 KDirStat (also by Stefan Hundhammer). While a number of
people contributed small patches and fixes, the project is largely a
one-man-show.
This manual page was written by Stefan Hundhammer
based on the initial one written for QDirStat by Patrick Matth\[:a]i
.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU General Public License, Version 2 any
later version published by the Free Software Foundation.
qdirstat-1.8/qdirstat.pro 0000664 0000000 0000000 00000001477 14112476455 0015614 0 ustar 00root root 0000000 0000000 # Toplevel qmake .pro file. Create a Makefile from this with
#
# qmake
#
# Then build the program with
#
# make
#
# Then install it with
#
# sudo make install
#
# By default, everyting is installed to /usr.
# If you want to install to, say, /usr/local, set INSTALL_PREFIX:
#
# qmake INSTALL_PREFIX=/usr/local
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = src scripts doc doc/stats man
macx {
# FIXME: Prevent build failure because of missing main() (issue #131)
# This is a pretty radical approach, and you won't get any of the scripts
# or any of the documentation on MacOS X; but it works.
#
# If anybody with good MacOS X know-how has a better idea that is still
# robust enough to prevent that same build failure to reappear, please open
# a pull request.
SUBDIRS = src
}
qdirstat-1.8/qdirstat.pro.user 0000664 0000000 0000000 00000047662 14112476455 0016577 0 ustar 00root root 0000000 0000000
ProjectExplorer.Project.ActiveTarget
0
ProjectExplorer.Project.EditorSettings
true
false
true
Cpp
CppGlobal
QmlJS
QmlJSGlobal
2
UTF-8
false
4
false
true
1
true
0
true
2
8
true
1
true
false
true
true
ProjectExplorer.Project.PluginSettings
ProjectExplorer.Project.Target.0
Desktop
Desktop
{888b365f-2bde-4794-8b79-baa82c8a4ec2}
0
0
0
true
qmake
QtProjectManager.QMakeBuildStep
false
false
false
true
Make
Qt4ProjectManager.MakeStep
-w
-r
false
2
Build
ProjectExplorer.BuildSteps.Build
true
Make
Qt4ProjectManager.MakeStep
-w
-r
true
clean
1
Clean
ProjectExplorer.BuildSteps.Clean
2
false
Release
Qt4ProjectManager.Qt4BuildConfiguration
0
true
1
0
Deploy
ProjectExplorer.BuildSteps.Deploy
1
Deploy locally
ProjectExplorer.DefaultDeployConfiguration
1
false
false
false
false
true
0.01
10
true
1
25
1
true
false
true
valgrind
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
src
Qt4ProjectManager.Qt4RunConfiguration:/work/home/sh/src/qdirstat/src/src.pro
~/src
src/src.pro
false
false
3768
true
false
false
false
true
false
false
false
false
true
0.01
10
true
1
25
1
true
false
true
valgrind
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
doc
Qt4ProjectManager.Qt4RunConfiguration:/work/home/sh/src/qdirstat/doc/doc.pro
doc/doc.pro
false
false
3768
false
true
false
false
true
false
false
false
false
true
0.01
10
true
1
25
1
true
false
true
valgrind
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
scripts
Qt4ProjectManager.Qt4RunConfiguration:/work/home/sh/src/qdirstat/scripts/scripts.pro
scripts/scripts.pro
false
false
3768
false
true
false
false
true
3
ProjectExplorer.Project.TargetCount
1
ProjectExplorer.Project.Updater.EnvironmentId
{69a2b64a-6740-4d76-a751-dfd1210c7360}
ProjectExplorer.Project.Updater.FileVersion
15
qdirstat-1.8/screenshots/ 0000775 0000000 0000000 00000000000 14112476455 0015566 5 ustar 00root root 0000000 0000000 qdirstat-1.8/screenshots/QDirStat-buckets-table.png 0000664 0000000 0000000 00000206160 14112476455 0022517 0 ustar 00root root 0000000 0000000 PNG
IHDR 3 A pHYs + tIME
~ &iTXtComment