31

I know I can do this to get a list of directory names:

find . -type d -maxdepth 1 

The output looks like this:

.
./foo
./bar

I prefer the listing without ./. Is there a way to get find to output just the raw names?

I tried sending the list to stat to format it but that just gives me the same result:

find . -type d -maxdepth 1 -print0 | xargs -0 stat -f '%N'
  • so you want foo bar ... all on one line without the ./ in front? – Levon Aug 24 '12 at 13:22
  • Is this purely for cosmetic / aesthetic reasons or are you trying to do something with the output? – jw013 Aug 24 '12 at 13:29
37

With GNU find you can use the -printf option:

find . -maxdepth 1 -type d -printf '%f\n'

As noted by Paweł in the comments, if you don't want the current directory to be listed add -mindepth 1, e.g.:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\n'
  • I cannot find any mention of the -printf option in the latest POSIX spec and I wonder how portable it is ... – rahmu Aug 25 '12 at 13:37
  • @rahmu: This was tested with GNU find. None of the printf options are mentioned by POSIX and they do not seem to be supported by some of the other find versions. GNU find can be installed in most places, so in that sense it is portable. – Thor Aug 25 '12 at 13:52
  • 1
    also add -mindepth 1 if you want to get rid of the . – Paweł Prażak Sep 26 '17 at 9:20
16

Update:

A shorter alternative:

 find . -maxdepth 1 -type d | cut -c 3-

Will give you the names, one per line, without any slashes

  • 4
    @downvoter .. a downvote without explanation doesn't help anyone (OP, SO or me). This is a functional solution to OP's question. I am happy to correct an error if pointed out or improve the answer, but that requires constructive feedback rather than just an anonymous "click". – Levon Aug 24 '12 at 14:02
  • 1
    I'm the one who downvoted when your answer included parsing ls. At the same time I had posted a link on why this is a bad idea on another answer that got deleted since. At the time there were only 2 answers and the reason seemed obvious. I'm glad you pointed out the ambiguity, and here's my explanation. For the record, I turned my downvote in an upvote because I agree with your current answer. – rahmu Aug 25 '12 at 13:30
  • @rahmu Giving an explanation for your downvote in another question is not helpful to me (and only obvious to you). Also, while this is a better solution, the solution I had posted before worked just fine (yes, I am familiar with your "don't use ls" link - but it doesn't apply blindly in all cases). If you have a counter example for why my initial solution wouldn't have worked, I'd love to know it (so that I can actually learn something from this), otherwise you are just posting a link and not offering anything constructive. – Levon Aug 25 '12 at 16:33
  • Consider there's a \n in a directory name you cannot use cut to retrieve it (which is what you were doing when I downvoted you). There are few cases where ls doesn't behave dangerously and it's almost always safer to use another way. – rahmu Aug 25 '12 at 17:17
8

Using GNU find, you can use -mindepth to prevent find from matching the current directory:

find . -type d -maxdepth 1 -mindepth 1

Since you are not doing this recursively, you can use a bash glob:

echo */

Adding a trailing / to a glob will cause only directories to be matched.

  • 1
    */ misses dot files and includes symlinks. This may or may not be a problem. – Gilles Aug 24 '12 at 23:18
  • @Gilles - It will always miss symlinks, but dotfiles depends on whether or not dotglob is set. – jordanm Aug 25 '12 at 0:16
6

Let sed remove those two characters:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'
6

I'd rather use:

 find ./ -type d -maxdepth 1 -exec basename {} \;
2

I usually use:

find * -type d

But I don't know if it's the right way to do what you want.

  • 1
    If you are going to let the shell expand all the filenames, why use find at all? – jordanm Aug 24 '12 at 16:14
  • @jordanm To select only directories. echo */ would do the same thing, more or less (it misses dot files and includes symlinks), but then joachim would ask how to remove the final /. – Gilles Aug 24 '12 at 23:17
0

In AIX does the parameter 'maxdepth' not work.

In general this works for me:

find ./ -type d | cut -d"/" -f2 | sort -u

0

What you are looking for is called basename, it ignore the unix directory structure

Example below:

find /any/path/you/want -maxdepth 1 -type d -exec basename {} \;

it will exclude for the output even the dir path, removing the necessity to cd before run the command


Some aditional info:

I'd pass -exec as argument to find instead |(pipe) another command for the output (avoiding the second command go over each output line, having said that, depending on the output it could improve the performance for the script)

NOTE: find options are not positional (-maxdepth affects tests specified before it as well as those specified after it).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.