Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.debian.user > #269730 > unrolled thread

tree with dir size

Started byNorthwind <nw@secubox.org>
First post2024-05-31 00:30 +0200
Last post2024-05-31 03:30 +0200
Articles 20 on this page of 27 — 10 participants

Back to article view | Back to linux.debian.user


Contents

  tree with dir size Northwind <nw@secubox.org> - 2024-05-31 00:30 +0200
    Re: tree with dir size eben@gmx.us - 2024-05-31 01:00 +0200
      Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-05-31 01:00 +0200
        Re: tree with dir size Northwind <nw@secubox.org> - 2024-05-31 01:00 +0200
          Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-05-31 01:10 +0200
        Re: tree with dir size eben@gmx.us - 2024-05-31 02:10 +0200
          Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-05-31 02:20 +0200
            Re: tree with dir size Franco Martelli <martellif67@gmail.com> - 2024-05-31 21:20 +0200
              Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-05-31 22:10 +0200
                Re: tree with dir size David Wright <deblis@lionunicorn.co.uk> - 2024-06-01 04:40 +0200
                  Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-06-01 05:20 +0200
                    Re: tree with dir size Lee <ler762@gmail.com> - 2024-06-01 16:20 +0200
                Re: tree with dir size Franco Martelli <martellif67@gmail.com> - 2024-06-03 16:00 +0200
                  Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-06-03 16:40 +0200
                    Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-06-03 21:10 +0200
                      Re: tree with dir size David Wright <deblis@lionunicorn.co.uk> - 2024-06-04 02:40 +0200
                    Re: tree with dir size Franco Martelli <martellif67@gmail.com> - 2024-06-03 22:50 +0200
                      Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-06-04 00:30 +0200
                        Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-06-04 03:50 +0200
                          Re: tree with dir size Greg Wooledge <greg@wooledge.org> - 2024-06-04 16:50 +0200
                          Re: tree with dir size Franco Martelli <martellif67@gmail.com> - 2024-06-04 16:50 +0200
                  Re: tree with dir size Andy Smith <andy@strugglers.net> - 2024-06-03 16:40 +0200
                    Re: tree with dir size <tomas@tuxteam.de> - 2024-06-03 19:10 +0200
                    Re: tree with dir size Franco Martelli <martellif67@gmail.com> - 2024-06-03 23:00 +0200
                  Re: tree with dir size <tomas@tuxteam.de> - 2024-06-03 16:40 +0200
    Re: tree with dir size Sridhar M A <alaymari@gmail.com> - 2024-05-31 02:50 +0200
    Re: tree with dir size Felix Miata <mrmazda@earthlink.net> - 2024-05-31 03:30 +0200

Page 1 of 2  [1] 2  Next page →


#269730 — tree with dir size

FromNorthwind <nw@secubox.org>
Date2024-05-31 00:30 +0200
Subjecttree with dir size
Message-ID<IJWrv-gZp6-5@gated-at.bofh.it>
Hello,

is there a command that shows dir/subdir structure like `tree`, but for 
each dir has the size in results as well?

Thanks.

[toc] | [next] | [standalone]


#269732

Fromeben@gmx.us
Date2024-05-31 01:00 +0200
Message-ID<IJWUx-gZyF-3@gated-at.bofh.it>
In reply to#269730
On 5/30/24 18:28, Northwind wrote:
> Hello,
>
> is there a command that shows dir/subdir structure like `tree`, but for each
> dir has the size in results as well?

It looks like "tree --du" should do it, but "tree -d --du -h" says

├── [452K]  Documents

when du says it's 787M.

--
When we've nuked the world to a cinder, the cockroaches picking
over the remains will be crawling over the remaining artifacts
and wondering what "PC LOAD LETTER" means. -- PC / ASR

[toc] | [prev] | [next] | [standalone]


#269733

FromGreg Wooledge <greg@wooledge.org>
Date2024-05-31 01:00 +0200
Message-ID<IJWUx-gZyF-1@gated-at.bofh.it>
In reply to#269732
On Thu, May 30, 2024 at 06:51:30PM -0400, eben@gmx.us wrote:
> It looks like "tree --du" should do it, but "tree -d --du -h" says
> 
> ├── [452K]  Documents
> 
> when du says it's 787M.

Well, that sounds like one of the numbers includes subdirectories and
the other only includes files in the immediate directory.

The question is: which one do you want?

[toc] | [prev] | [next] | [standalone]


#269734

FromNorthwind <nw@secubox.org>
Date2024-05-31 01:00 +0200
Message-ID<IJWUx-gZyF-7@gated-at.bofh.it>
In reply to#269733

both the size of current path and subdir should be expected.

thanks.

> The question is: which one do you want?

[toc] | [prev] | [next] | [standalone]


#269736

FromGreg Wooledge <greg@wooledge.org>
Date2024-05-31 01:10 +0200
Message-ID<IJX4d-gZU0-7@gated-at.bofh.it>
In reply to#269734
On Fri, May 31, 2024 at 06:57:27AM +0800, Northwind wrote:
> both the size of current path and subdir should be expected.

According to the man page, that's what it does.

I just installed tree and tried it.  There's a subtle behavior that I
did not expect:

hobbit:/usr/local$ tree -d --du -h
[3.9M]  .
├── [4.0K]  bin
├── [4.0K]  etc

Those number are definitely not totals for the files in a directory.
Compare:

hobbit:/usr/local$ tree --du -h | less
[627M]  .
├── [ 81M]  bin
│   ├── [7.6K]  addcr

It looks like the -d option makes it only look at the size of the raw
directory (4096 bytes, as in

hobbit:/usr/local$ ls -ld bin
drwxr-sr-x 2 root staff 4096 Feb 17 15:14 bin/

) rather than the total of the files within the directory.

Solution: don't use -d.  But then you get all the files listed instead
of just the directories.

If there's a way to get the pruning of files of -d plus the total-printing
of omitting -d then I don't know what it is.

The best workaround I can immediately see is to include -F to put trailing
slashes on the directories, and then grep for those.

hobbit:/usr/local$ tree --du -h -F | grep /$ | head
[627M]  ./
├── [ 81M]  bin/
├── [4.0K]  etc/
├── [4.0K]  games/
├── [126K]  include/
│   └── [122K]  opus/
├── [ 42M]  lib/
│   ├── [3.4M]  nethackdir/
│   │   ├── [4.0K]  save/
│   ├── [4.3K]  pkgconfig/

[toc] | [prev] | [next] | [standalone]


#269745

Fromeben@gmx.us
Date2024-05-31 02:10 +0200
Message-ID<IJY0h-h0zf-5@gated-at.bofh.it>
In reply to#269733
On 5/30/24 18:54, Greg Wooledge wrote:
> On Thu, May 30, 2024 at 06:51:30PM -0400, eben@gmx.us wrote:
>> It looks like "tree --du" should do it, but "tree -d --du -h" says
>>
>> ├── [452K]  Documents
>>
>> when du says it's 787M.
>
> Well, that sounds like one of the numbers includes subdirectories and
> the other only includes files in the immediate directory.

 From du(1):

        --du   For  each directory report its size as the accumulation of
               sizes of all its files and sub-directories (and their files,
               and so on).  The total amount of used space is also given in
               the final report (like the 'du -c' command.) This option
               requires tree to read the entire directory tree before
               emitting it, see BUGS AND NOTES below.  Implies -s.

OK, now for "du -c".  From du(1):

        -c, --total
               produce a grand total

Well, that doesn't help much.

> The question is: which one do you want?

I'd like the size of the entire tree, and I think that's what OP wants too.

I think "du -h -S -s Documents/" gives just the files in Documents, and not
its subdirectories, and it gives 269M.  "ls -ldh Documents/" says the
directory itsely takes up 36k, so I'm not sure where "tree" got that number.

[toc] | [prev] | [next] | [standalone]


#269749

FromGreg Wooledge <greg@wooledge.org>
Date2024-05-31 02:20 +0200
Message-ID<IJY9X-h0Cm-5@gated-at.bofh.it>
In reply to#269745
On Thu, May 30, 2024 at 08:04:26PM -0400, eben@gmx.us wrote:
> > > It looks like "tree --du" should do it, but "tree -d --du -h" says
> > > ├── [452K]  Documents
> I think "du -h -S -s Documents/" gives just the files in Documents, and not
> its subdirectories, and it gives 269M.  "ls -ldh Documents/" says the
> directory itsely takes up 36k, so I'm not sure where "tree" got that number.

Hmm.  Guessing again, it might be the sum of all the "-d" raw directory
sizes of the directory and its subdirectories, but still ignoring files?
I can't fathom why the programmer(s) decided to do this, because it
isn't useful to anybody, but it's the only answer I can come up with.

hobbit:~$ mkdir -p /tmp/x/y
hobbit:~$ tree --du -dh /tmp/x
[8.0K]  /tmp/x
└── [4.0K]  y

hobbit:~$ cp /vmlinuz /tmp/x
hobbit:~$ tree --du -dh /tmp/x
[8.0K]  /tmp/x
└── [4.0K]  y

Confusing and useless.  I still don't have a better answer than this:

hobbit:~$ tree --du -Fh /tmp/x | grep /$
[7.8M]  /tmp/x/
└── [4.0K]  y/

[toc] | [prev] | [next] | [standalone]


#269776

FromFranco Martelli <martellif67@gmail.com>
Date2024-05-31 21:20 +0200
Message-ID<IKfXb-hhoO-1@gated-at.bofh.it>
In reply to#269749
On 31/05/24 at 02:18, Greg Wooledge wrote:
> Confusing and useless.  I still don't have a better answer than this:
> 
> hobbit:~$ tree --du -Fh /tmp/x | grep /$
> [7.8M]/tmp/x/
> └── [4.0K]  y/

It could be improved adding the "-a" switch to show also the hidden 
directories and the "--color" switch to the "grep" command but this 
sadly doesn't show the expected result (colorized directories) I don't 
know why:

~$ tree --du -Fah /tmp/x | grep --color /$

Me too needed to summarize the directory's size thus I wrote a bash 
function to accomplish this and added it to my /etc/profile.d/local.sh file:

duhs() { IFS=$'\n\r' ; for d in $(/usr/bin/find $1 -maxdepth 1 -type d 
|/usr/bin/sort) ; do du -hs $d ; done }

It doesn't show the output like "tree" does but it works nicely.

Cheers,
-- 
Franco Martelli

[toc] | [prev] | [next] | [standalone]


#269777

FromGreg Wooledge <greg@wooledge.org>
Date2024-05-31 22:10 +0200
Message-ID<IKgJz-hhTQ-25@gated-at.bofh.it>
In reply to#269776
On Fri, May 31, 2024 at 09:18:03PM +0200, Franco Martelli wrote:
> On 31/05/24 at 02:18, Greg Wooledge wrote:
> > Confusing and useless.  I still don't have a better answer than this:
> > 
> > hobbit:~$ tree --du -Fh /tmp/x | grep /$
> > [7.8M]/tmp/x/
> > └── [4.0K]  y/
> 
> It could be improved adding the "-a" switch to show also the hidden
> directories and the "--color" switch to the "grep" command but this sadly
> doesn't show the expected result (colorized directories) I don't know why:
> 
> ~$ tree --du -Fah /tmp/x | grep --color /$

You're only coloring the trailing / characters.  If you want everything
from after the last space to the end of the line, you'd want:

    tree --du -Fh /usr/local | grep --color '[^[:space:]]*/$'

Of course this fails to colorize the entire directory name if there's
a space in it.

> Me too needed to summarize the directory's size thus I wrote a bash function
> to accomplish this and added it to my /etc/profile.d/local.sh file:
> 
> duhs() { IFS=$'\n\r' ; for d in $(/usr/bin/find $1 -maxdepth 1 -type d
> |/usr/bin/sort) ; do du -hs $d ; done }

This, too, will fail if there are spaces in a directory name.  You'd need
to quote the "$1" and "$d" at the very least.  The for d in $(find) part
is also quite fragile; I see you tried to work around that by using IFS,
but that's not a full fix.  Also, you never declared IFS as a local
variable in this function, so you will be altering IFS in any shell that
actually runs this function.

Consider this one instead:

hobbit:~$ duhs() { du -hs "${1:-.}"/*/; }
hobbit:~$ duhs /usr/local
81M     /usr/local/bin/
4.0K    /usr/local/etc/
4.0K    /usr/local/games/
136K    /usr/local/include/
45M     /usr/local/lib/
29M     /usr/local/man/
8.0K    /usr/local/sbin/
2.2M    /usr/local/share/
484M    /usr/local/src/
44M     /usr/local/tcl8.6/

In bash, a glob that ends with / will match directories only.  Globs are
always sorted, so you can also drop the call to sort.  The only issue
with this version is if the number of subdirectories is so large that
it triggers the "Argument list too long" error.

If you want to avoid that, you can use xargs -0:

    duhs() { printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh; }

As printf is a bash builtin, it can handle an unlimited number of
arguments.  So this form should work in all cases.

[toc] | [prev] | [next] | [standalone]


#269784

FromDavid Wright <deblis@lionunicorn.co.uk>
Date2024-06-01 04:40 +0200
Message-ID<IKmOZ-hlwF-1@gated-at.bofh.it>
In reply to#269777
On Fri 31 May 2024 at 16:03:22 (-0400), Greg Wooledge wrote:
> On Fri, May 31, 2024 at 09:18:03PM +0200, Franco Martelli wrote:
> > On 31/05/24 at 02:18, Greg Wooledge wrote:
> > > Confusing and useless.  I still don't have a better answer than this:
> > > 
> > > hobbit:~$ tree --du -Fh /tmp/x | grep /$
> > > [7.8M]/tmp/x/
> > > └── [4.0K]  y/
> > 
> > It could be improved adding the "-a" switch to show also the hidden
> > directories and the "--color" switch to the "grep" command but this sadly
> > doesn't show the expected result (colorized directories) I don't know why:
> > 
> > ~$ tree --du -Fah /tmp/x | grep --color /$
> 
> You're only coloring the trailing / characters.  If you want everything
> from after the last space to the end of the line, you'd want:
> 
>     tree --du -Fh /usr/local | grep --color '[^[:space:]]*/$'
> 
> Of course this fails to colorize the entire directory name if there's
> a space in it.

If a coloured ] is unimportant, I suppose you could use:

  tree --du -Fh whatever | grep --color '][[:space:]][[:space:]].*/$'

Cheers,
David.

[toc] | [prev] | [next] | [standalone]


#269786

FromGreg Wooledge <greg@wooledge.org>
Date2024-06-01 05:20 +0200
Message-ID<IKnrH-hlZi-1@gated-at.bofh.it>
In reply to#269784
On Fri, May 31, 2024 at 09:35:59PM -0500, David Wright wrote:
> If a coloured ] is unimportant, I suppose you could use:
> 
>   tree --du -Fh whatever | grep --color '][[:space:]][[:space:]].*/$'

You don't need to count spaces.  Just '].*/$' would suffice.  We already
know we want to start with the first ] character on the line, no matter
how many spaces follow it.

I really question the usefulness of colorizing the directory names,
but since we're already this far down the rabbit hole, we might as
well light some dynamite to make the hole deeper.  I'm sure it's safe!

We're using GNU grep for coloring, so we can also use its PCRE syntax
to do "lookbehind" voodoo:

    tree --du -Fh /usr/local | grep --color -P '(?<=]).*/$'

which means "start matching after a ] but don't include the ] in the
match".

[toc] | [prev] | [next] | [standalone]


#269806

FromLee <ler762@gmail.com>
Date2024-06-01 16:20 +0200
Message-ID<IKxKp-hswd-1@gated-at.bofh.it>
In reply to#269786
On Fri, May 31, 2024 at 11:18 PM Greg Wooledge wrote:
>
> On Fri, May 31, 2024 at 09:35:59PM -0500, David Wright wrote:
> > If a coloured ] is unimportant, I suppose you could use:
> >
> >   tree --du -Fh whatever | grep --color '][[:space:]][[:space:]].*/$'
>
> You don't need to count spaces.  Just '].*/$' would suffice.  We already
> know we want to start with the first ] character on the line, no matter
> how many spaces follow it.
>
> I really question the usefulness of colorizing the directory names,
> but since we're already this far down the rabbit hole, we might as
> well light some dynamite to make the hole deeper.  I'm sure it's safe!
>
> We're using GNU grep for coloring, so we can also use its PCRE syntax
> to do "lookbehind" voodoo:
>
>     tree --du -Fh /usr/local | grep --color -P '(?<=]).*/$'
>
> which means "start matching after a ] but don't include the ] in the
> match".

Or use  '\K' to cause previously matched characters to not be included
in the match:

   tree --du -Fah . | grep --color -P '[^]]*]  \K.*/$'

(which required entirely too much RTFMing to learn about '\K')

Regards,
Lee

[toc] | [prev] | [next] | [standalone]


#269866

FromFranco Martelli <martellif67@gmail.com>
Date2024-06-03 16:00 +0200
Message-ID<ILgo9-kbf-1@gated-at.bofh.it>
In reply to#269777
Hi Greg,
(sorry for the answer's late but I turn off the PC during the weekend) :(

On 31/05/24 at 22:03, Greg Wooledge wrote:
>> It could be improved adding the "-a" switch to show also the hidden
>> directories and the "--color" switch to the "grep" command but this sadly
>> doesn't show the expected result (colorized directories) I don't know why:
>>
>> ~$ tree --du -Fah /tmp/x | grep --color /$
> You're only coloring the trailing / characters.  If you want everything
> from after the last space to the end of the line, you'd want:
> 
>      tree --du -Fh /usr/local | grep --color '[^[:space:]]*/$'

I realized why "tree" command doesn't colorized the directories: "tree" 
detects that its std output goes through a pipe and therefore it 
disables the escaped code to colorize (like also "dmesg" does).
To avoid this behavior you must use the "unbuffer" command:

unbuffer tree --du -Fah /usr/local | grep /$

You can also try:

~# unbuffer dmesg | grep snd

/usr/bin/unbuffer is part of the "expect" package.

...> If you want to avoid that, you can use xargs -0:
> 
>     duhs() { printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh; }
> 
> As printf is a bash builtin, it can handle an unlimited number of
> arguments.  So this form should work in all cases.

Thank you very much for revolutionizing my duhs() function, but sadly 
this version omits to show the hidden directories. Do you have a version 
that it shows also those directories? For me it's so hard to figure out 
what the  "${1:-.}"/*/  block does.
Again, is "man 7 glob" the right read or do you have a better one?

Cheers,
-- 
Franco Martelli

[toc] | [prev] | [next] | [standalone]


#269868

FromGreg Wooledge <greg@wooledge.org>
Date2024-06-03 16:40 +0200
Message-ID<ILh0R-kDd-7@gated-at.bofh.it>
In reply to#269866
On Mon, Jun 03, 2024 at 03:52:54PM +0200, Franco Martelli wrote:
> On 31/05/24 at 22:03, Greg Wooledge wrote:
> > > It could be improved adding the "-a" switch to show also the hidden
> > > directories and the "--color" switch to the "grep" command but this sadly
> > > doesn't show the expected result (colorized directories) I don't know why:
> > > 
> > > ~$ tree --du -Fah /tmp/x | grep --color /$
> > You're only coloring the trailing / characters.  If you want everything
> > from after the last space to the end of the line, you'd want:
> > 
> >      tree --du -Fh /usr/local | grep --color '[^[:space:]]*/$'
> 
> I realized why "tree" command doesn't colorized the directories: "tree"
> detects that its std output goes through a pipe and therefore it disables
> the escaped code to colorize (like also "dmesg" does).
> To avoid this behavior you must use the "unbuffer" command:
> 
> unbuffer tree --du -Fah /usr/local | grep /$

According to tree(1) there's a -C option which should force tree's
coloring to be always on, even when stdout goes to a pipe.  But tree
never colors anything for me, even with -C and no pipe, so I don't know
what else is needed.

> ...> If you want to avoid that, you can use xargs -0:
> > 
> >     duhs() { printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh; }
> > 
> > As printf is a bash builtin, it can handle an unlimited number of
> > arguments.  So this form should work in all cases.
> 
> Thank you very much for revolutionizing my duhs() function, but sadly this
> version omits to show the hidden directories. Do you have a version that it
> shows also those directories? For me it's so hard to figure out what the
> "${1:-.}"/*/  block does.

"$1" is the first argument given to the function.  It can also be written
as "${1}".

"${1:-default}" is the first argument given to the function, *or* the
constant string 'default' if the first argument is empty or not given.
Therefore, "${1:-.}" is "the first argument, or default to . if no
argument is given".

Since that part is quoted, whatever value is used is taken as a string,
with no word splitting or globbing applied.  That means it will handle
directory names that contain spaces, asterisks, etc.

Given the glob "x"/*/ the shell will look for all the subdirectories
of "x".  The trailing / forces it to ignore anything that isn't a
directory.

You can see it in action:

hobbit:~$ printf '%s\n' /usr/local/*/
/usr/local/bin/
/usr/local/etc/
/usr/local/games/
/usr/local/include/
/usr/local/lib/
/usr/local/man/
/usr/local/sbin/
/usr/local/share/
/usr/local/src/
/usr/local/tcl8.6/

So, putting it all together, that glob says "all the subdirectories of
the first argument, or all the subdirectories of . if there was no
argument given".

Getting it to include directory names that begin with . is trickier.
The simplest way would be to turn on bash's dotglob option, and then
turn it off again at the end:

duhs() {
    shopt -s dotglob
    printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
    shopt -u dotglob
}

But this assumes that the option was *not* already on when we entered
the function.  If it was on, we've just turned it off.  Another way to
do this, which doesn't permanently alter the option for the remainder
of the shell's lifetime, would be to wrap the function body in a subshell:

duhs() {
    (
      shopt -s dotglob
      printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
    )
}

The formatting choices here are legion.

There are a few other options, but they become increasingly arcane from
here.  The subshell is probably the most straightforward choice.  The
function is already forking child processes, so from a performance point
of view, adding a subshell won't be much worse.

I'll also throw in one last piece of information because if I don't,
someone else is likely to do it, without a good explanation.
Syntactically, the body of a shell function doesn't have to be enclosed
in curly braces.  The body can be any compound command, and a curly-brace
command group is just one example of a compound command.  A subshell is
another example.  So, it could also be written this way:

duhs() (
    shopt -s dotglob
    printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
)

I'm not personally fond of this.  It's extremely easy to overlook
the fact that the curly braces have been replaced with parentheses,
especially in certain fonts.  Nevertheless, some people like this.

[toc] | [prev] | [next] | [standalone]


#269885

FromGreg Wooledge <greg@wooledge.org>
Date2024-06-03 21:10 +0200
Message-ID<ILle9-nkr-1@gated-at.bofh.it>
In reply to#269868
On Mon, Jun 03, 2024 at 01:11:57PM -0500, David Wright wrote:
> On Mon 03 Jun 2024 at 10:32:16 (-0400), Greg Wooledge wrote:
> > duhs() (
> >     shopt -s dotglob
> >     printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
> > )
> > 
> > I'm not personally fond of this.  It's extremely easy to overlook
> > the fact that the curly braces have been replaced with parentheses,

> I guess minimalists would make a one-liner out of that.
> Myself, I prefer verbosity, and the ability to search and find
> all my functions with   /function.*{$   in less. For example,
> I write what is probably my most trivial function in .bashrc as:
> 
>   function _Cat_ {
>       cat
>   }
> 
> rather than:
> 
>   _Cat_() { cat; }

... I feel like you've just exemplified what I was talking about, missing
the fact that the curly braces were replaced with parentheses around the
function body to force a subshell every time it's called.

It had nothing to do with how many lines of code were used.  I could
have written them as

    duhs() { (shopt -s dotglob; printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh); }

and

    duhs() (shopt -s dotglob; printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh)

and the same point would have applied.

>   function _Cat_ {

Do note that the "function" keyword is a bash/ksh extension, and not
part of POSIX sh syntax.  In bash, "x()" and "function x" are identical
in behavior.  In ksh, they cause two different kinds of variable scoping
behavior.  Bash also allows "function x()" which ksh does not.

Just for the record.

[toc] | [prev] | [next] | [standalone]


#269913

FromDavid Wright <deblis@lionunicorn.co.uk>
Date2024-06-04 02:40 +0200
Message-ID<ILqnv-qmI-3@gated-at.bofh.it>
In reply to#269885
On Mon 03 Jun 2024 at 15:03:37 (-0400), Greg Wooledge wrote:
> On Mon, Jun 03, 2024 at 01:11:57PM -0500, David Wright wrote:
> > On Mon 03 Jun 2024 at 10:32:16 (-0400), Greg Wooledge wrote:
> > > duhs() (
> > >     shopt -s dotglob
> > >     printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
> > > )
> > > 
> > > I'm not personally fond of this.  It's extremely easy to overlook
> > > the fact that the curly braces have been replaced with parentheses,
> 
> > I guess minimalists would make a one-liner out of that.
> > Myself, I prefer verbosity, and the ability to search and find
> > all my functions with   /function.*{$   in less. For example,
> > I write what is probably my most trivial function in .bashrc as:
> > 
> >   function _Cat_ {
> >       cat
> >   }
> > 
> > rather than:
> > 
> >   _Cat_() { cat; }
> 
> ... I feel like you've just exemplified what I was talking about, missing
> the fact that the curly braces were replaced with parentheses around the
> function body to force a subshell every time it's called.

  _Puss_() ( cat )

if it makes you happy; but no, you made your point about parentheses
perfectly well. It's just that _Cat_ doesn't require a subshell for
/its/ purpose.

> It had nothing to do with how many lines of code were used.  I could
> have written them as
> 
>     duhs() { (shopt -s dotglob; printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh); }
> 
> and
> 
>     duhs() (shopt -s dotglob; printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh)
> 
> and the same point would have applied.
> 
> >   function _Cat_ {
> 
> Do note that the "function" keyword is a bash/ksh extension, and not
> part of POSIX sh syntax.  In bash, "x()" and "function x" are identical
> in behavior.  In ksh, they cause two different kinds of variable scoping
> behavior.  Bash also allows "function x()" which ksh does not.
> 
> Just for the record.

Noted. (Franco did mention using bash, and I mentioned .bashrc.)
I'm a bit old for switching shells now!

Cheers,
David.

[toc] | [prev] | [next] | [standalone]


#269899

FromFranco Martelli <martellif67@gmail.com>
Date2024-06-03 22:50 +0200
Message-ID<ILmMV-o6h-1@gated-at.bofh.it>
In reply to#269868
On 03/06/24 at 16:32, Greg Wooledge wrote:
> duhs() {
>      shopt -s dotglob
>      printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
>      shopt -u dotglob
> }
> 
> But this assumes that the option was*not*  already on when we entered
> the function.  If it was on, we've just turned it off.  Another way to
> do this, which doesn't permanently alter the option for the remainder
> of the shell's lifetime, would be to wrap the function body in a subshell:
> 
> duhs() {
>      (
>        shopt -s dotglob
>        printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
>      )
> }

I've some issue with this function. It doesn't show the size of the 
directory specified as argument, it follows the output of my original 
function:

duhs1() { IFS=$'\n\r' ; for d in $(/usr/bin/find $1 -maxdepth 1 -type d 
|/usr/bin/sort) ; do du -hs $d ; done }

~# duhs1 /usr/local/
88K     /usr/local/     ←←←
4,0K    /usr/local/bin
4,0K    /usr/local/etc
...

According to the very kind Greg's explanation I tried to change the 
function in this way:

duhs() {
     (
       shopt -s dotglob
       du -sh "${1:-.}"
       printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
     )
}

the specified directory is shown, but the output has became messed up:

~# duhs /usr/local/
88K     /usr/local/
4,0K    /usr/local//bin/
4,0K    /usr/local//etc/
4,0K    /usr/local//games/
4,0K    /usr/local//include/
4,0K    /usr/local//man/
4,0K    /usr/local//sbin/
56K     /usr/local//share/
4,0K    /usr/local//src/

and worst the size of /usr/local/share isn't 56K:

~# du -hs /usr/local/share/
60K     /usr/local/share/

as it's shown by my original function:

~# duhs1 /usr/local/
88K     /usr/local/
4,0K    /usr/local/bin
4,0K    /usr/local/etc
4,0K    /usr/local/games
4,0K    /usr/local/include
4,0K    /usr/local/sbin
60K     /usr/local/share
4,0K    /usr/local/src

the /usr/local/man/ isn't listed by the "find" command because it's a 
symlink:

~# ls -l /usr/local/man
lrwxrwxrwx 1 root root 9 21 giu  2023 /usr/local/man -> share/man

Is there a way to have duhs() function that it doesn't print a double 
"/" at the end of the specified directory?
The size mismatch of /usr/local/share could depend by /usr/local/man is 
a symlink of 4K's size to a directory embedded in /usr/local/share, am I 
right?

Cheers,
-- 
Franco Martelli

[toc] | [prev] | [next] | [standalone]


#269910

FromGreg Wooledge <greg@wooledge.org>
Date2024-06-04 00:30 +0200
Message-ID<ILolH-p9f-13@gated-at.bofh.it>
In reply to#269899
On Mon, Jun 03, 2024 at 10:45:28PM +0200, Franco Martelli wrote:
> On 03/06/24 at 16:32, Greg Wooledge wrote:
> > duhs() {
> >      (
> >        shopt -s dotglob
> >        printf '%s\0' "${1:-.}"/*/ | xargs -0 du -sh
> >      )
> > }
> 
> I've some issue with this function. It doesn't show the size of the
> directory specified as argument, it follows the output of my original
> function:

I started writing a response to this, because it seemed easy enough to
fix -- just add "${1:-.}" to the printf arguments, so it gets passed
along to du -sh, and included in the output.

But then I tested it.

hobbit:~$ du -sh /usr/local /usr/local/bin
684M    /usr/local

What?  Where's the second line?

hobbit:~$ du -sh /usr/local/bin /usr/local/etc
81M     /usr/local/bin
4.0K    /usr/local/etc

Multiple arguments are allowed....

hobbit:~$ du -sh /usr/local/bin /usr/local/etc /usr/local
81M     /usr/local/bin
4.0K    /usr/local/etc
603M    /usr/local

You're even allowed to have a parent directory after its children...

hobbit:~$ du -sh /usr/local /usr/local/bin /usr/local/etc
684M    /usr/local

... but if the parent is FIRST, the children get... swallowed up by
it?  Huh?  And if the parent is last, then the value shown for the
parent excludes the children that were already reported on?

Why the HELL is it like this?!

It doesn't even match its own documentation.  Here's what the info
page says:

‘-s’
‘--summarize’
     Display only a total for each argument.

There's supposed to be a total *FOR EACH ARGUMENT*.  There isn't.

OK, I officially wash my hands of ANY solution based on du -s.  If
you want to try to make it work sensibly, more power to you.  As far
as I'm concerned, though, this is broken.  Irreparably broken.

It looks like tree(1) is less broken, so it might be better to stick
with that, even if you have to pipe the output through grep to get what
you want.

*Sigh*.

[toc] | [prev] | [next] | [standalone]


#269914

FromGreg Wooledge <greg@wooledge.org>
Date2024-06-04 03:50 +0200
Message-ID<ILrtf-qXB-3@gated-at.bofh.it>
In reply to#269910
On Mon, Jun 03, 2024 at 07:42:17PM -0500, David Wright wrote:
> On Mon 03 Jun 2024 at 18:29:17 (-0400), Greg Wooledge wrote:
> > ‘-s’
> > ‘--summarize’
> >      Display only a total for each argument.
> > 
> > There's supposed to be a total *FOR EACH ARGUMENT*.  There isn't.
> 
> Try adding -l. The idea is that du is trying to avoid double-counting,
> so when the subdirectories come first, those ones are "used up" by
> the time it reaches the parent. When the parent is first, it's (all)
> the subdirectories instead that have been "used up".

‘-l’
‘--count-links’
     Count the size of all files, even if they have appeared already (as
     a hard link).

This documentation leaves a lot to be desired.

Anyway, you are correct about the result, even if the documentation gives
no realistic way to conclude such a result.

hobbit:~$ printf '%s\0' "${1:-.}" "${1:-.}"/*/ | xargs -0 du -shl
684M    /usr/local
81M     /usr/local/bin/
4.0K    /usr/local/etc/
4.0K    /usr/local/games/
136K    /usr/local/include/
45M     /usr/local/lib/
29M     /usr/local/man/
8.0K    /usr/local/sbin/
31M     /usr/local/share/
484M    /usr/local/src/
44M     /usr/local/tcl8.6/

[toc] | [prev] | [next] | [standalone]


#269925

FromGreg Wooledge <greg@wooledge.org>
Date2024-06-04 16:50 +0200
Message-ID<ILDE5-yuR-1@gated-at.bofh.it>
In reply to#269914
On Tue, Jun 04, 2024 at 04:40:07PM +0200, Franco Martelli wrote:
> FYI the revision of duhs() I adopt is:
> 
> duhs() { ( shopt -s dotglob; printf '%s\0' "${1:-.}" "${1:-.}"*/ | xargs -0
> du -shl ) }                                                ↑
> 
> Please note that I dropped a "/" in the "${1:-.}"/*/ block because the
> directories listed had a double "//" in their names:

That's because you're passing directories with a trailing / from your
shell.  Probably because you're using tab completions.

If you pass "/usr/local" as the argument instead of

> ~# duhs /usr/local/
> 88K     /usr/local/
> 4,0K    /usr/local//bin/
> 4,0K    /usr/local//etc/
> 4,0K    /usr/local//games/
> 4,0K    /usr/local//include/
> 4,0K    /usr/local//man/
> 4,0K    /usr/local//sbin/
> 60K     /usr/local//share/
> 4,0K    /usr/local//src/

you will see that you've broken it now.

If you really care about removing the double slashes from the case
where you pass an extra trailing slash in your input, you should use
parameter expansions or some other filtering to remove one of the
slashes.  That would be better than breaking your function.

duhs() {
    (
      shopt -s dotglob
      s=${1:-.}
      s=${s%/}
      printf '%s\0' "${s:-.}" "${s:-.}"/*/ | xargs -0 du -shl
    )
}

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.debian.user


csiph-web