GNU bug report logs - #21218
ls -d

Previous Next

Package: coreutils;

Reported by: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>

Date: Sat, 8 Aug 2015 00:14:02 UTC

Severity: normal

Tags: notabug

Done: Eric Blake <eblake <at> redhat.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 21218 in the body.
You can then email your comments to 21218 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Sat, 08 Aug 2015 00:14:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to "Sneeh, Eddie" <eddie.sneeh <at> roche.com>:
New bug report received and forwarded. Copy sent to bug-coreutils <at> gnu.org. (Sat, 08 Aug 2015 00:14:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
To: bug-coreutils <at> gnu.org
Subject: ls -d
Date: Fri, 7 Aug 2015 17:01:06 -0700
[Message part 1 (text/plain, inline)]
Hi,
I believe there is a problem with ls -d (unless the intent is to just list
1 directory).
Say I have a dir mydir, it has directories d1 and d2, and files f1 and f2.
I want to list only d1 and d2.  How do I do that?  I tried ls -d but that
doesn't seem to work:
\ls -d mydir
returns: mydir
\ls -d mydir/*
returns: mydir/d1 mydir/d2 mydir/f1 mydir/f2
but f1 and f2 are files.

How can I achieve the following:
\ls ?????? mydir
to return: mydir/d1 mydir/d2



-- 
Best Regards,
*Eddie Sneeh*
[Message part 2 (text/html, inline)]

Added tag(s) notabug. Request was from Eric Blake <eblake <at> redhat.com> to control <at> debbugs.gnu.org. (Sat, 08 Aug 2015 03:44:02 GMT) Full text and rfc822 format available.

Reply sent to Eric Blake <eblake <at> redhat.com>:
You have taken responsibility. (Sat, 08 Aug 2015 03:44:02 GMT) Full text and rfc822 format available.

Notification sent to "Sneeh, Eddie" <eddie.sneeh <at> roche.com>:
bug acknowledged by developer. (Sat, 08 Aug 2015 03:44:03 GMT) Full text and rfc822 format available.

Message #12 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>, 21218-done <at> debbugs.gnu.org
Subject: Re: bug#21218: ls -d
Date: Fri, 7 Aug 2015 21:43:30 -0600
[Message part 1 (text/plain, inline)]
tag 21218 notabug
thanks

On 08/07/2015 06:01 PM, Sneeh, Eddie wrote:
> Hi,
> I believe there is a problem with ls -d (unless the intent is to just list
> 1 directory).

Thanks for the report.  However, I think you have misunderstood the
purpose of -d.  Try this for comparison:

touch file
ls . file
ls -d . file

All -d does is to list command line arguments that are directories as
the name of the directory itself, rather than descending and showing the
directory's contents.

> Say I have a dir mydir, it has directories d1 and d2, and files f1 and f2.
> I want to list only d1 and d2.  How do I do that?  I tried ls -d but that
> doesn't seem to work:
> \ls -d mydir
> returns: mydir
> \ls -d mydir/*
> returns: mydir/d1 mydir/d2 mydir/f1 mydir/f2
> but f1 and f2 are files.

If you want to list ONLY directories, use a glob that guarantees only
directories can be matched:

ls -d mydir/*/

The trailing slash can only match directories, and will therefore skip
ordinary files.  Or, you can use find:

find mydir -mindepth 1 -maxdepth 2 -type d

I'm closing this as not a bug as ls is working as designed, but feel
free to ask further questions.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Sat, 08 Aug 2015 11:01:02 GMT) Full text and rfc822 format available.

Message #15 received at submit <at> debbugs.gnu.org (full text, mbox):

From: "Rainer M. Canavan" <coreutils <at> canavan.de>
To: bug-coreutils <at> gnu.org
Subject: Re: bug#21218: ls -d
Date: Sat, 8 Aug 2015 12:59:50 +0200 (CEST)
Eric Blake <eblake <at> redhat.com> wrote:

[...]

> All -d does is to list command line arguments that are directories as
> the name of the directory itself, rather than descending and showing the
> directory's contents.

That description is already better than the current one in the
man page, which reads:

       -d, --directory
              list directory entries instead of contents, and do not  derefer-
              ence symbolic links

I'd say that one can reasonably be understood to mean that files would
not be listed, as Eddie did. I'd suggest a new wording:

       -d, --directory
              If an argument is a directory, list the directory itself 
              instead of its contents. Frequently used with -l to display
              the properties of directories.

I don't see any relevant effect on symbolic links, so unless soeone can
come up with an explanation, maybe that part can be dropped.

$ ls -ld b   
lrwxr-xr-x 1 canavan user 1 Aug  8 12:45 b -> a
$ ls -l b
lrwxr-xr-x 1 canavan user 1 Aug  8 12:45 b -> a
$ ls -d b
b
$ ls  b
b

rainer




Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Sun, 09 Aug 2015 18:48:01 GMT) Full text and rfc822 format available.

Message #18 received at 21218 <at> debbugs.gnu.org (full text, mbox):

From: Bob Proulx <bob <at> proulx.com>
To: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
Cc: 21218 <at> debbugs.gnu.org
Subject: Re: bug#21218: ls -d
Date: Sun, 9 Aug 2015 12:47:23 -0600
Sneeh, Eddie wrote:
> I believe there is a problem with ls -d (unless the intent is to just list
> 1 directory).

Just noting this has an FAQ entry:

  http://www.gnu.org/software/coreutils/faq/coreutils-faq.html#ls-_002dd-does-not-list-directories_0021

Bob




Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Mon, 10 Aug 2015 19:29:02 GMT) Full text and rfc822 format available.

Message #21 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 21218-done <at> debbugs.gnu.org
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 12:09:21 -0700
[Message part 1 (text/plain, inline)]
Hi Eric, thanks for the quick response and clarification.  I wasn't
completely clear what -d was supposed to do exactly.  The man pages define
ls -d as:
*"list directory entries instead of contents".*
The files in the target directory are contents of that directory, but they
get listed anyway!   I still think ls -d is not accurate.   Here are some
examples:
% \ls -d f1
f1
(but f1 is not a "directory entry" so this output is not consistent with
the definition above.)

If:
% \ls /tmp/mydir
d1/ d2/ f1 f2
% \ls -d .
.
(but where are the rest of the directories?)
% \ls -d /tmp/mydir
/tmp/mydir
(Same thing, no listing of directory entries in that directory as the
definition says)
The behavior I'm seeing is:  list directory entries instead of contents, *but
not including the parent directory (or the directory specified as argument)*.
I guess that's where the confusion is.  IMHO, the directory that the user
specifies should be the first to follow the rule, because that's what the
user is concerned about the most.
% \ls -d *
can be accomplished by a simple:
% \ls
% \ls -d <directory I'm concerned about)
just does a pwd!


Thanks for the find command.  That's what most of us have been doing, but I
feel that listing directories/files/links should be an ls function more so
than a find's, and it should be a simple command rather than a long one.
If it were up to me, this is what I would do:
% ls -f  (list files)
% ls -l (list links)
% ls -d (list directories)
This is more intuitive and useful, at least to me.
The man pages for ls -f say: "do not sort"  I'm not sure how -f was derived
from that.
Since these switches are already taken to do other things, what do you
think about this:
% ls -fo (list files only)
% ls -lo (list links only)
% ls -do (list directories only)

For now, I like your solution: ls -d */   which I'll be using instead of
the find command.  I'll have to "tolerate" the extra slash at the end, but
I like this better than other options.   Thanks again.

Eddie






On Fri, Aug 7, 2015 at 8:43 PM, Eric Blake <eblake <at> redhat.com> wrote:

> tag 21218 notabug
> thanks
>
> On 08/07/2015 06:01 PM, Sneeh, Eddie wrote:
> > Hi,
> > I believe there is a problem with ls -d (unless the intent is to just
> list
> > 1 directory).
>
> Thanks for the report.  However, I think you have misunderstood the
> purpose of -d.  Try this for comparison:
>
> touch file
> ls . file
> ls -d . file
>
> All -d does is to list command line arguments that are directories as
> the name of the directory itself, rather than descending and showing the
> directory's contents.
>
> > Say I have a dir mydir, it has directories d1 and d2, and files f1 and
> f2.
> > I want to list only d1 and d2.  How do I do that?  I tried ls -d but that
> > doesn't seem to work:
> > \ls -d mydir
> > returns: mydir
> > \ls -d mydir/*
> > returns: mydir/d1 mydir/d2 mydir/f1 mydir/f2
> > but f1 and f2 are files.
>
> If you want to list ONLY directories, use a glob that guarantees only
> directories can be matched:
>
> ls -d mydir/*/
>
> The trailing slash can only match directories, and will therefore skip
> ordinary files.  Or, you can use find:
>
> find mydir -mindepth 1 -maxdepth 2 -type d
>
> I'm closing this as not a bug as ls is working as designed, but feel
> free to ask further questions.
>
> --
> Eric Blake   eblake redhat com    +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
>
>


-- 
Best Regards,
*Eddie Sneeh*
[Message part 2 (text/html, inline)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Mon, 10 Aug 2015 19:42:01 GMT) Full text and rfc822 format available.

Message #24 received at 21218 <at> debbugs.gnu.org (full text, mbox):

From: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
To: Bob Proulx <bob <at> proulx.com>
Cc: 21218 <at> debbugs.gnu.org, Eric Blake <eblake <at> redhat.com>
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 12:40:22 -0700
[Message part 1 (text/plain, inline)]
Hi Bob, thanks for the info.
If ya'll don't want to consider this a bug, that's fine, but I suggest
updating the definition for -d to clarify the true behavior.  If it must be
used with other options for it to be useful, then the definition should say
so because I sure don't see "list directory entries instead of contents".
I'm yet to see the usefulness of this option (used alone), other than in
Eric's example, which is what I was after.
If someone has some examples of ls -d usage, *without adding other switches* ,
I'd appreciate it.
Thanks again,
Eddie


On Sun, Aug 9, 2015 at 11:47 AM, Bob Proulx <bob <at> proulx.com> wrote:

> Sneeh, Eddie wrote:
> > I believe there is a problem with ls -d (unless the intent is to just
> list
> > 1 directory).
>
> Just noting this has an FAQ entry:
>
>
> http://www.gnu.org/software/coreutils/faq/coreutils-faq.html#ls-_002dd-does-not-list-directories_0021
>
> Bob
>



-- 
Best Regards,
*Eddie Sneeh*
[Message part 2 (text/html, inline)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Mon, 10 Aug 2015 20:38:02 GMT) Full text and rfc822 format available.

Message #27 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: Assaf Gordon <assafgordon <at> gmail.com>
To: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
Cc: Eric Blake <eblake <at> redhat.com>, 21218-done <at> debbugs.gnu.org
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 20:36:44 +0000
Hello Eddie,

(replying to your two last messages together)

On Mon, Aug 10, 2015 at 12:09:21PM -0700, Sneeh, Eddie wrote:
>Hi Eric, thanks for the quick response and clarification.  I wasn't
>completely clear what -d was supposed to do exactly.  The man pages define
>ls -d as:
>*"list directory entries instead of contents".*

The wording above is perhaps not clear, and indeed, recent versions of 
GNU coreutils it have been re-worded to:

    -d
    --directory
         List just the names of directories, as with other
         types of files, rather than listing their contents.
    (in http://www.gnu.org/software/coreutils/manual/html_node/Which-files-are-listed.html#Which-files-are-listed)

And:
    -d, --directory      list directories themselves, not their contents
    (from 'ls --help' or 'man ls')

POSIX explains it as so:

    -d
    [...] Do not treat directories differently than other types of files.
    (in http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html)

And OpenBSD explains it as:

    -d      Directories are listed as plain files
    (from 'man ls' on OpenBSD - this is not GNU Coreutils' ls)

The term "directory entries" refers to the technical item of a "file 
system entry", which represent the information about the directory 
itself (e.g. when was it created and who is the owner). This term was 
indeed confusing, and so it was changed in 2013 in this commit:
http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=da398ae5dfa43efda48310899c24242da4764f44

To give a concrete example:

    # This means: list information about files INSIDE directory f1
    ls -l f1

    # This means: list information about directory f1 itself
    # (such as who is the owner, access permissions,
    # and when was it created)
    ls -ld f1

(replying to your second message):

On 08/10/2015 03:40 PM, Sneeh, Eddie wrote:
> Hi Bob, thanks for the info.
> If ya'll don't want to consider this a bug, that's fine, but I suggest 
> updating the definition for -d to clarify the true behavior.

The wording has been already updated, so that's fixed.

> I'm yet to see the usefulness of this option (used alone), other than 
> in Eric's example, which is what I was after.
> If someone has some examples of ls -d usage, _without adding other 
> switches_ , I'd appreciate it.

I can give a contrived example, but hopefully it will demonstrate that 
there are some uses cases.

Imagine the following content of a directory:

    touch a1 a2 a3 b1 b2 b3
    mkdir b4
    touch b4/foo

To list everything, typing 'ls' would suffice:

    $ ls
    1  2  3  4  6  a1  a2  a3  b1  b2  b3  b4

Now, I want to see only 'things' starting with 'b'.
Note that by 'things' I mean both files and directories.
From a purely technical POV, on many file-systems
a 'directory' is just a file, but with a different file-system type,
so sometimes technical purists will say 'files' and also mean 
directories (and similarly, special devices, named fifos, sockets - they 
are all 'files').
back to listing things starting with 'b':

    $ ls b*
    b1  b2  b3

    b4:
    foo

The above might be unexpected output. Because 'b4' is a directory, ls 
entered it and listed its content (foo).
If I want to see only list of things (=files,directories,everything),
that's where '-d' comes in handy:

    $ ls -d b*
    b1 b2 b3 b4

> For now, I like your solution: ls -d */   which I'll be using instead 
> of the find command. 

If you use 'ls */' to view directories interactively, that's fine.

If you use it for any kind of scripting (e.g. in a shell for/while loop 
or xargs), then it is highly recommended to use 'find' instead of 'ls' - 
a file containing any kind of funky characters (spaces, tabs, newlines, 
etc.) might confuse your script and cause unintended conseqeunces.

To save some typing, you can create the following shell function
(e.g. in your '~/.bashrc' file):

    lsd(){ find ${1:-.} -mindepth 1 -maxdepth 1 -type d -printf "%f\n";}

And then run 'lsd' or 'lsd DIR' to list the current or the specified 
directory.

In scripting, it is recommended to use '-print0' to prevent issues
with files that might contain whitespaces, e.g.:

    find DIR -mindepth 1 -maxdepth 1 -type d -print0 \
        | xargs -0 -I% echo "Processing directory %"


Regards,
 - assaf




Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Mon, 10 Aug 2015 20:48:01 GMT) Full text and rfc822 format available.

Message #30 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: Eric Blake <eblake <at> redhat.com>
To: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
Cc: 21218-done <at> debbugs.gnu.org
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 14:47:29 -0600
[Message part 1 (text/plain, inline)]
On 08/10/2015 01:09 PM, Sneeh, Eddie wrote:

> Since these switches are already taken to do other things, what do you
> think about this:
> % ls -fo (list files only)
> % ls -lo (list links only)
> % ls -do (list directories only)

Won't work.  'ls -o' is already a valid command, so 'ls -fo' is the same
as 'ls -o -f' or 'ls -f -o'.  You can't start a long-option name with a
single dash; at least, not in coreutils which uses getopt_long() (there
are some exceptions, like gcc, which use getopt_long_only() for
historical reasons, and which therefore can spell long options with a
single dash if there is no ambiguity, but use of getopt_long_only() is
not recommended in new programs).

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

[signature.asc (application/pgp-signature, attachment)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Mon, 10 Aug 2015 21:09:02 GMT) Full text and rfc822 format available.

Message #33 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
To: Eric Blake <eblake <at> redhat.com>
Cc: 21218-done <21218-done <at> debbugs.gnu.org>
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 14:07:45 -0700
[Message part 1 (text/plain, inline)]
Ah yes -do is the same as -d -o, overlooked that.  Looks like most the
alphabet is already taken, o is taken, n is taken, l is taken, is y still
available? (Am I seeing this right, only -e and -y are still unused?)


On Mon, Aug 10, 2015 at 1:47 PM, Eric Blake <eblake <at> redhat.com> wrote:

> On 08/10/2015 01:09 PM, Sneeh, Eddie wrote:
>
> > Since these switches are already taken to do other things, what do you
> > think about this:
> > % ls -fo (list files only)
> > % ls -lo (list links only)
> > % ls -do (list directories only)
>
> Won't work.  'ls -o' is already a valid command, so 'ls -fo' is the same
> as 'ls -o -f' or 'ls -f -o'.  You can't start a long-option name with a
> single dash; at least, not in coreutils which uses getopt_long() (there
> are some exceptions, like gcc, which use getopt_long_only() for
> historical reasons, and which therefore can spell long options with a
> single dash if there is no ambiguity, but use of getopt_long_only() is
> not recommended in new programs).
>
> --
> Eric Blake   eblake redhat com    +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
>
>


-- 
Best Regards,
*Eddie Sneeh*
[Message part 2 (text/html, inline)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Mon, 10 Aug 2015 23:25:02 GMT) Full text and rfc822 format available.

Message #36 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
To: Assaf Gordon <assafgordon <at> gmail.com>
Cc: Eric Blake <eblake <at> redhat.com>, 21218-done <21218-done <at> debbugs.gnu.org>
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 16:24:10 -0700
[Message part 1 (text/plain, inline)]
Hi Assaf, I appreciate the thought and effort that went into constructing
your reply.

If you agree that the man pages are intended for all users, not just sys
admins, then the definition of a directory would be a container of other
things (files, links, directories).   It does not mean a regular file.
 (Let's take devices/sockts/etc... out of the discussion.  The majority of
people don't deal with them.)

Based on this definition of "directory", and keeping things simple and
logical, if I wanted a listing of directories/files/links, what makes sense
to me is ls (the definition being *list directory contents*).  If I wanted
to look for specific patterns, then find may be a better choice.  Your
example: ls -d b* does list directories at the current level (and it
doesn't descend into subdirectories -- that's good), but it also lists
*files* and *links* starting with the letter b!
Try \ls -d d* f* l*
It's going to list directories, and files and links.  (in my example, d:
directory, f: file, l: slink)

I guess what it boils down to is "-d" is a confusing choice of option for
what it really does.  "ls --directory" has little to do with directories,
(and adding the word "themselves" to the definition doesn't really remove
much ambiguity), -d lists everything at one level, non-directories included!

Again, imho, what I suggested is more intuitive:
ls -d (list directories)
ls -f (list files)
ls -l (list links)
The current -d should have been something like: --1level or --dont_descend
or the like.
I understand it's very difficult and late for any changes to happen.
Thanks for listening!  Your detailed response was, again, very much
appreciated!

Eddie





On Mon, Aug 10, 2015 at 1:36 PM, Assaf Gordon <assafgordon <at> gmail.com> wrote:

> Hello Eddie,
>
> (replying to your two last messages together)
>
> On Mon, Aug 10, 2015 at 12:09:21PM -0700, Sneeh, Eddie wrote:
>
>> Hi Eric, thanks for the quick response and clarification.  I wasn't
>> completely clear what -d was supposed to do exactly.  The man pages define
>> ls -d as:
>> *"list directory entries instead of contents".*
>>
>
> The wording above is perhaps not clear, and indeed, recent versions of GNU
> coreutils it have been re-worded to:
>
>     -d
>     --directory
>          List just the names of directories, as with other
>          types of files, rather than listing their contents.
>     (in
> http://www.gnu.org/software/coreutils/manual/html_node/Which-files-are-listed.html#Which-files-are-listed
> )
>
> And:
>     -d, --directory      list directories themselves, not their contents
>
     (from 'ls --help' or 'man ls')

>
> POSIX explains it as so:
>
>     -d
>     [...] Do not treat directories differently than other types of files.
>     (in http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html)
>
> And OpenBSD explains it as:
>
>     -d      Directories are listed as plain files
>     (from 'man ls' on OpenBSD - this is not GNU Coreutils' ls)
>
> The term "directory entries" refers to the technical item of a "file
> system entry", which represent the information about the directory itself
> (e.g. when was it created and who is the owner). This term was indeed
> confusing, and so it was changed in 2013 in this commit:
>
> http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=da398ae5dfa43efda48310899c24242da4764f44
>
> To give a concrete example:
>
>     # This means: list information about files INSIDE directory f1
>     ls -l f1
>
>     # This means: list information about directory f1 itself
>     # (such as who is the owner, access permissions,
>     # and when was it created)
>     ls -ld f1
>
> (replying to your second message):
>
> On 08/10/2015 03:40 PM, Sneeh, Eddie wrote:
>
>> Hi Bob, thanks for the info.
>> If ya'll don't want to consider this a bug, that's fine, but I suggest
>> updating the definition for -d to clarify the true behavior.
>>
>
> The wording has been already updated, so that's fixed.
>
> I'm yet to see the usefulness of this option (used alone), other than in
>> Eric's example, which is what I was after.
>> If someone has some examples of ls -d usage, _without adding other
>> switches_ , I'd appreciate it.
>>
>
> I can give a contrived example, but hopefully it will demonstrate that
> there are some uses cases.
>
> Imagine the following content of a directory:
>
>     touch a1 a2 a3 b1 b2 b3
>     mkdir b4
>     touch b4/foo
>
> To list everything, typing 'ls' would suffice:
>
>     $ ls
>     1  2  3  4  6  a1  a2  a3  b1  b2  b3  b4
>
> Now, I want to see only 'things' starting with 'b'.
> Note that by 'things' I mean both files and directories.
> From a purely technical POV, on many file-systems
> a 'directory' is just a file, but with a different file-system type,
> so sometimes technical purists will say 'files' and also mean directories
> (and similarly, special devices, named fifos, sockets - they are all
> 'files').
> back to listing things starting with 'b':
>
>     $ ls b*
>     b1  b2  b3
>
>     b4:
>     foo
>
> The above might be unexpected output. Because 'b4' is a directory, ls
> entered it and listed its content (foo).
> If I want to see only list of things (=files,directories,everything),
> that's where '-d' comes in handy:
>
>     $ ls -d b*
>     b1 b2 b3 b4
>
> For now, I like your solution: ls -d */   which I'll be using instead of
>> the find command.
>>
>
> If you use 'ls */' to view directories interactively, that's fine.
>
> If you use it for any kind of scripting (e.g. in a shell for/while loop or
> xargs), then it is highly recommended to use 'find' instead of 'ls' - a
> file containing any kind of funky characters (spaces, tabs, newlines, etc.)
> might confuse your script and cause unintended conseqeunces.
>
> To save some typing, you can create the following shell function
> (e.g. in your '~/.bashrc' file):
>
>     lsd(){ find ${1:-.} -mindepth 1 -maxdepth 1 -type d -printf "%f\n";}
>
> And then run 'lsd' or 'lsd DIR' to list the current or the specified
> directory.
>
> In scripting, it is recommended to use '-print0' to prevent issues
> with files that might contain whitespaces, e.g.:
>
>     find DIR -mindepth 1 -maxdepth 1 -type d -print0 \
>         | xargs -0 -I% echo "Processing directory %"
>
>
> Regards,
>  - assaf
>



-- 
Best Regards,
*Eddie Sneeh*
[Message part 2 (text/html, inline)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Tue, 11 Aug 2015 03:06:01 GMT) Full text and rfc822 format available.

Message #39 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: Assaf Gordon <assafgordon <at> gmail.com>
To: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
Cc: Eric Blake <eblake <at> redhat.com>, 21218-done <21218-done <at> debbugs.gnu.org>
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 23:05:42 -0400
Hello Eddie,

> On Aug 10, 2015, at 19:24, Sneeh, Eddie <eddie.sneeh <at> roche.com> wrote:

> I guess what it boils down to is "-d" is a confusing choice of option for what it really does.  "ls --directory" has little to do with directories, (and adding the word "themselves" to the definition doesn't really remove much ambiguity), -d lists everything at one level, non-directories included!

I can see why this might be confusing.
If there are suggestions for improved wording (while still being concise and clear), then it might be possible to change the help/man pages.

However, regarding the functionality of '-d' - that I'm quite certain will not change.
It is a long-established behavior of 'ls', one that has been standard on many operating systems and for many years (possibly decades? I'm too new to know for sure).

But perhaps look at it from another perspective:

you've mentioned two requests of affecting ls's output:

> what I suggested is more intuitive:
> ls -d (list directories)
> ls -f (list files)
> ls -l (list links)
and:
> The current -d should have been something like: --1level or --dont_descend or the like.

When in fact, 'find' has exactly these options!

If you think of 'ls' as:
  list files, catering to the most common use-cases,
and think of 'find' as:
  list files with maximum flexibility of filters and conditions
then the distinction between them becomes clearer.

With find you can already performs your requested options:
  find -type f (list regular files)
  find -type l (list symbolic links)
  find -type d (list directories)
  find -maxdepth 1 (don't descend into sub-directories)

and 'find' allows you even more, because you can combine these conditions in as flexible way as you'd like.
for example, to list all directories up to 3 levels down, which start with 'b', owned by me and are writable:
  find . -maxdepth 3 -name "b*" -user assaf -writable
or, list all regular files in the current directory that have been accessed in the last 24 hours, and print their name and size:
   find . -maxdepth 1 -type f -atime 1 -printf "%s %f\n"

My point is, the moment you need more than basic listing of files,
you should switch from 'ls' to 'find'.
This way we can avoid adding more functionality to 'ls' because it already exists in 'find'.

regards,
 - assaf









Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Tue, 11 Aug 2015 03:59:02 GMT) Full text and rfc822 format available.

Message #42 received at 21218-done <at> debbugs.gnu.org (full text, mbox):

From: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
To: Assaf Gordon <assafgordon <at> gmail.com>
Cc: Eric Blake <eblake <at> redhat.com>, 21218-done <21218-done <at> debbugs.gnu.org>
Subject: Re: bug#21218: ls -d
Date: Mon, 10 Aug 2015 20:57:54 -0700
[Message part 1 (text/plain, inline)]
Thanks again Assaf, please see below...


On Mon, Aug 10, 2015 at 8:05 PM, Assaf Gordon <assafgordon <at> gmail.com> wrote:

> Hello Eddie,
>
> > On Aug 10, 2015, at 19:24, Sneeh, Eddie <eddie.sneeh <at> roche.com> wrote:
>
> > I guess what it boils down to is "-d" is a confusing choice of option
> for what it really does.  "ls --directory" has little to do with
> directories, (and adding the word "themselves" to the definition doesn't
> really remove much ambiguity), -d lists everything at one level,
> non-directories included!
>
> I can see why this might be confusing.
> If there are suggestions for improved wording (while still being concise
> and clear), then it might be possible to change the help/man pages.
>

 The problem is the behavior of ls -d is so erratic it's difficult to
describe in a concise way.  I haven't seen the code or the spec, so my
suggestion is based solely on observation (which may or may not be
complete).  Here's one shot at it, see if you agree or disagree with it:
-d:   --directory, --donotdescend:   Useful only when "*" is part of the
argument(s).  The same as ls but does not descend into subdirectories.
​
​Adding ​
--donotdescend
​provides
a little bit of
​"credibility" and ​
a true meaning to -d because certainly --directory doesn't make much sense.
​  I assure you, every user I've worked with over the years that had a
question about this was as confused as me.​

However, regarding the functionality of '-d' - that I'm quite certain will
> not change.
> It is a long-established behavior of 'ls', one that has been standard on
> many operating systems and for many years (possibly decades? I'm too new to
> know for sure).
>

​Yeah, this is not something that I've just discovered suddenly; I don't
know why I decided to "complain" today.
​
​An unusually slow Monday perhaps.  ​
I'm fully aware that changing the behavior of ls -d , -f , -l etc.. is not
practical, not the right thing to do, but what can be done
​, for the sake of improvement, ​
​is to provide
a clearer definition that reflects the true behavior
​, something along the lines of what I suggested above.

​


>
> But perhaps look at it from another perspective:
>
> you've mentioned two requests of affecting ls's output:
>
> > what I suggested is more intuitive:
> > ls -d (list directories)
> > ls -f (list files)
> > ls -l (list links)
> and:
> > The current -d should have been something like: --1level or
> --dont_descend or the like.
>
> When in fact, 'find' has exactly these options!
>

​My point is, when a user wants to* list *directory contents, they think *ls
*first*.*

"find" is a very useful utility, I like it a lot, and I use it a lot.
There are no issues with "find", and this is not about how to use "find",
it's about "ls -d".  Appreciate the intent and the helpful examples though.
​

>
> If you think of 'ls' as:
>   list files, catering to the most common use-cases,
> and think of 'find' as:
>   list files with maximum flexibility of filters and conditions
> then the distinction between them becomes clearer.
>
> With find you can already performs your requested options:
>   find -type f (list regular files)
>   find -type l (list symbolic links)
>   find -type d (list directories)
>   find -maxdepth 1 (don't descend into sub-directories)
>
> and 'find' allows you even more, because you can combine these conditions
> in as flexible way as you'd like.
> for example, to list all directories up to 3 levels down, which start with
> 'b', owned by me and are writable:
>   find . -maxdepth 3 -name "b*" -user assaf -writable
> or, list all regular files in the current directory that have been
> accessed in the last 24 hours, and print their name and size:
>    find . -maxdepth 1 -type f -atime 1 -printf "%s %f\n"
>
> My point is, the moment you need more than basic listing of files,
> you should switch from 'ls' to 'find'.
> This way we can avoid adding more functionality to 'ls' because it already
> exists in 'find'.
>
> regards,
>  - assaf
>
>
>
>
>
>
>


-- 
Best Regards,
*Eddie Sneeh*
[Message part 2 (text/html, inline)]

Information forwarded to bug-coreutils <at> gnu.org:
bug#21218; Package coreutils. (Wed, 12 Aug 2015 18:36:01 GMT) Full text and rfc822 format available.

Message #45 received at 21218 <at> debbugs.gnu.org (full text, mbox):

From: Bob Proulx <bob <at> proulx.com>
To: "Sneeh, Eddie" <eddie.sneeh <at> roche.com>
Cc: 21218 <at> debbugs.gnu.org
Subject: Re: bug#21218: ls -d
Date: Wed, 12 Aug 2015 12:35:10 -0600
Sneeh, Eddie wrote:
>  The problem is the behavior of ls -d is so erratic it's difficult to
> describe in a concise way.

This statement pains me to read.  Because it shows that there is still
a misunderstanding on ls and ls -d.

> I haven't seen the code or the spec, so my suggestion is based
> solely on observation (which may or may not be complete).

Let me try to describe it.  In the beginning that we care about was
the Unix file system.  In this file system everything is a file[1].  I
am going to say that again.  Everything is a file.

Some files are special files.  Most files in /dev are special files
such as the block and character devices that immediately people think
about.  But directories are files too!  Directories are simply files
in the Unix file system.  Directories are another example of special
files.

The 'ls' command reads directories, which are special files, and lists
their contents.  The primary purpose of 'ls' is to list directories.
Focus on that task.  Read the directory file.  List it out.  Here is
an example.  In my example I am going to talk classically and simply
and acknowledge that some of the system and library calls have been
modernized but that doesn't matter because the behavior remains the
same.

  ls /

The 'ls' command will have one program argument.  That one program
argument is the "/" string.  The 'ls' program will stat(2) the
argument to see if it exists and if it is a directory.  If it is a
directory then it will treat it specially and call opendir(3) on that
string.  If that succeeds then it reads the directory and lists out
the content.  It only does this for directories.  In this way
directories are treated specially by 'ls'.  If the program argument is
not a identified by stat(2) as a directory then it is simply printed
out normally.

If 'ls' is not given any program arguments then it defaults to listing
the "." directory.  The 'ls' command without arguments:

  ls

Is the same as:

  ls .

This is the same thing.  The 'ls' program opens the "." string and
gets a handle to the file.  It then reads the directory and lists the
contents found there.

What about shell wildcards?

First they are called *shell* wildcards.  They don't have anything to
do with 'ls' at all.  The shell, typically /bin/bash, scans the
command line and *replaces* any shell wildcard with the expansion of
the file glob.  The '*' is called a file glob because it replaces a
glob of characters.  There are also [...]'s too.  This replacement
happens at the command line level and happens before the shell
invocation of 'ls'.

  mkdir test
  cd test
  touch file1.txt file2.txt file3.txt
  ls ./*.txt
  ...the ./*.txt is expanded and replaced by the shell...
  ls file1.txt file2.txt file3.txt
  ...the 'ls' command has three program arguments provided by the shell...
    file1.txt file2.txt file3.txt

The 'ls' program has no way of knowing it was invoked with a shell
wildcard.  The shell replaced that wildcard before ls was launched.
All the 'ls' program knows is that it has a list of program
arguments.  It will walk through each of them in turn and list them
out program argument by program argument.

Now consider this and this next example.

  mkdir dir1.d
  touch dir1.d/file11.txt
  touch dir1.d/file12.txt
  ls -log *.*
    -rw-rw-r-- 1  0 Aug 12 11:33 file1.txt
    -rw-rw-r-- 1  0 Aug 12 11:33 file2.txt
    -rw-rw-r-- 1  0 Aug 12 11:33 file3.txt

    dir1.d:
    total 0
    -rw-rw-r-- 1 0 Aug 12 11:42 file11.txt
    -rw-rw-r-- 1 0 Aug 12 11:46 file12.txt

Not that the files file1.txt, file2.txt file3.txt plus dir1.d were
what was listed.  The files file11.txt and file12.txt are part of the
dir1.d listing.  It is subtle but it is really dir1.d that is being
listed.

That is useful.  But it is also often not desired.  What has happened?
Let's use 'echo' to show what program arguments the the shell is using
to invoke the 'ls' command.

  echo ls *.*
    ls dir1.d file1.txt file2.txt file3.txt

And so here we see that 'ls' has four program arguments.  The dir1.d
argument is a directory.  Therefore 'ls' reads the directory and lists
the contents.  And in doing so the directory itself is skipped from
the listing.  What is the permissions on dir1.d?

  ls -log .
    total 0
    drwxrwxr-x 2 80 Aug 12 11:46 dir1.d
    -rw-rw-r-- 1  0 Aug 12 11:33 file1.txt
    -rw-rw-r-- 1  0 Aug 12 11:33 file2.txt
    -rw-rw-r-- 1  0 Aug 12 11:33 file3.txt

Okay.  The "." directory was listed.  That included the entire
directory.  But I just want to list the dir1.d directory by itself.

  ls -log *.d

Same as just listing the directory.  I just want to see the
permissions on the directory and not the contents.

  ls -log dir1.d
    total 0
    -rw-rw-r-- 1 0 Aug 12 11:42 file11.txt
    -rw-rw-r-- 1 0 Aug 12 11:46 file12.txt

That isn't listing the directory.  Because 'ls' has a program argument
and it is a directory it is listing the contents of the directory.
But I want to list the permissions on the directory itself!

How can this be prevented?  How can we instruct 'ls' that it should
not recurse down into a directory listed as a program argument?  If
only there were some 'ls' option to prevent it treating directories as
special.

There is.  This is the '-d' option.  At least as early as 1979 in V7
the 'ls' command included the '-d' to prevent it treating directories
specially.  If the '-d' option is applied then 'ls' won't treat
program arguments that are directories any different than any other
argument.  The 'ls' command will simply print it for display the same
as any other entry.

  ls -ldog dir1.d
    drwxrwxr-x 2 80 Aug 12 11:46 dir1.d

Which also allows us to use it this way too.

  ls -ldog ./*.*
    drwxrwxr-x 2 80 Aug 12 11:46 ./dir1.d
    -rw-rw-r-- 1  0 Aug 12 11:33 ./file1.txt
    -rw-rw-r-- 1  0 Aug 12 11:33 ./file2.txt
    -rw-rw-r-- 1  0 Aug 12 11:33 ./file3.txt

As a quick aside here I always list wildcards ./* or similarly.
Because otherwise files starting with a '-' option start character
might be confused with being a filename.  With ./* that would be
expanded to be ./- and that will be avoided.  Pedantically I should
use '--' to explicitly say I am done listing options.  But personally
I always use ./* as a personal preference.

  ls -ldog -- *.*

And so we have the '-d' option.  The purpose of which is to list the
any directory arguments themselves and not their contents.  In the V7
docs it described it saying, "If the argument is a directory, list
only its name, not its contents (mostly used with '-l' to get status
on directory)."  The coreutils documentation says:

  ‘-d’
  ‘--directory’
     List just the names of directories, as with other types of files,
     rather than listing their contents.

As you can see this has nothing to do with filtering what is
displayed.  Nor with selecting what is displayed.  The '-d' changes
how 'ls' treats directories listed as program arguments.  If the
program argument is not a directory then it has nothing to do.

This is why when people try 'ls -d *.txt' it is unlikely to ever be
what they want.  It is unlikely that file1.txt would ever be a
directory.  If it isn't a directory then the -d option won't have
anything to do anything in that context.  The caller may be wanting ls
to select based upon the type of the object file but that isn't
related to using the '-d' option.  And specifically selecting files
(finding files) by file type is exactly what 'find' does which is why
everyone always redirects such questions to 'find'.

Bob

P.S.

> Assaf Gordon wrote:
> > It is a long-established behavior of 'ls', one that has been
> > standard on many operating systems and for many years (possibly
> > decades? I'm too new to know for sure).

Try 40 years.  You can read the V7 source and see it there.  After
four decades it truly is long standing behavior. :-)

[1] In Unix everything is a file.  Leading to a joke that in the Linux
kernel everything is a file system.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 10 Sep 2015 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 9 years and 288 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.