Listing only directories using ls in bash: An exam

2019-01-05 06:22发布

This command lists directories in the current path: ls -d */

What exactly does the pattern */ do?

And how can we give the absolute path in the above command (e.g. ls -d /home/alice/Documents) for listing only directories in that path?

25条回答
不美不萌又怎样
2楼-- · 2019-01-05 07:14

4 (more) Reliable Options.

An unquoted asterisk * will be interpreted as a pattern (glob) by the shell.
The shell will use it in pathname expansion.
It will then generate a list of filenames that match the pattern.
A simple asterisk will match all filenames in the PWD (present working directory).
A more complex pattern as */ will match all filenames that end in /.
Thus, all directories. That is why the command:

1.- echo.

echo */
echo ./*/              ### avoid misinterpreting filenames like "-e dir"

will be expanded (by the shell) to echo all directories in the PWD.


To test this: Create a directory (mkdir) named like test-dir, and cd into it:

mkdir test-dir; cd test-dir

Create some directories:

mkdir {cs,files,masters,draft,static}   # safe directories.
mkdir {*,-,--,-v\ var,-h,-n,dir\ with\ spaces}  # some a bit less secure.
touch -- 'file with spaces' '-a' '-l' 'filename'    # and some files:

The command echo ./*/ will remain reliable even with odd named files:

./--/ ./-/ ./*/ ./cs/ ./dir with spaces/ ./draft/ ./files/ ./-h/
./masters/ ./-n/ ./static/ ./-v var/

But the spaces in filenames make reading a bit confusing.


If instead of echo, we use ls, the shell is still what is expanding the list of filenames. The shell is the reason to get a list of directories in the PWD. The -d option to ls makes it list the present directory entry instead of the contents of each directory (as presented by default).

ls -d */

However, this command is (somewhat) less reliable. It will fail with the odd named files listed above. It will choke with several names. You need to erase one by one till you find the ones with problems.

2.- ls

The GNU ls will accept the "end of options" (--) key.

ls -d ./*/                     ### more reliable BSD ls
ls -d -- */                    ### more reliable GNU ls

3.-printf

To list each directory in its own line (in one column, similar to ls -1), use:

$ printf "%s\n" */        ### Correct even with "-", spaces or newlines.

And, even better, we could remove the trailing /:

$ set -- */; printf "%s\n" "${@%/}"        ### Correct with spaces and newlines.

An attempt like this:

$ for i in $(ls -d */); do echo ${i%%/}; done

Will fail on:

  • some names (ls -d */) as already shown above.
  • will be affected by the value of IFS.
  • will split names on spaces and tabs (with default IFS).
  • each newline in the name will start a new echo command.

4.- Function

Finally, using the argument list inside a function will not affect the arguments list of the present running shell. Simply:

$ listdirs(){ set -- */; printf "%s\n" "${@%/}"; }
$ listdirs

presents this list:

--
-
*
cs
dir with spaces
draft
files
-h
masters
-n
static
-v var

This options are safe with several types of odd filenames.

查看更多
做自己的国王
3楼-- · 2019-01-05 07:15

Actual ls solution, including symlinks to directories

Many answers here don't actually use ls (or only use it in the trivial sense of ls -d, while using wildcards for the actual subdirectory matching. A true ls solution is useful, since it allows the use of ls options for sorting order, etc.

Excluding symlinks

One solution using ls has been given, but it does something different from the other solutions in that it excludes symlinks to directories:

ls -l | grep '^d'

(possibly piping through sed or awk to isolate the file names)

Including symlinks

In the (probably more common) case that symlinks to directories should be included, we can use the -p option of ls:

ls -1p | grep '/$'

or, getting rid of the trailing slashes:

ls -1p | grep '/$' | sed 's/\/$//'

We can add options to ls as needed (if a long listing is used, the -1 is no longer required).

note: if we want trailing slashes, but don't want them highlighted by grep, we can hackishly remove the highlighting by making the actual matched portion of the line empty:

ls -1p | grep -P '(?=/$)'
查看更多
虎瘦雄心在
4楼-- · 2019-01-05 07:15

Try this one. this will work on all distros ls -ltr | grep drw

查看更多
倾城 Initia
5楼-- · 2019-01-05 07:16

to show folder lists without /

ls -d */|sed 's|[/]||g'
查看更多
太酷不给撩
6楼-- · 2019-01-05 07:16

Here is what I am using

ls -d1 /Directory/Path/*;

查看更多
小情绪 Triste *
7楼-- · 2019-01-05 07:16

Here is what I use for listing only directory names:

ls -1d /some/folder/*/ | awk -F "/" "{print \$(NF-1)}"
查看更多
登录 后发表回答