I'd like to find all directories containing .txt files. But I need to print one level up the output.

For example, I'm using find to search recursively for .txt files in the current directory. Then only the directories containing such files are shown.

find . -name "*.txt" -printf '%h\n'

outputs to (for example)


So, I'd like to improve the use of find to:

  1. does not show repeated dirs (I think it happens because there are 2 .txt file therein)

  2. I'd like to print only the first level, that is, only ./out/ and ./output/

3 Answers 3


There might be a more find-centric way, but you could do it with a couple of other tools helping:

find . -name '*.txt' -printf '%h\n' | cut -f1,2 -d/ | sort -u

Or I guess we could save a process and use awk like

find . -name '*.txt' -printf '%h\n' | awk -F/ '{matched[$1"/"$2]=1} END {for(dir in matched) {print dir}}'
  • Since I have a lot of files and folders, which command could be faster?
    – Sigur
    Commented Jan 6, 2017 at 2:19
  • @Sigur my gut says the second, but I'd have to benchmark them to say for sure Commented Jan 6, 2017 at 2:22
  • What do you think about awk -F'/' '{print $1"/"$2}'. It is simpler, I think.
    – Sigur
    Commented Jan 6, 2017 at 2:24
  • 1
    @Sigur it's simpler, but won't remove duplicates Commented Jan 6, 2017 at 2:24
  • 1
    Actually, I think the first might run faster. Unless you have really long directory names that only have differences at the end, the sort is going to be extremely efficient, and probably better than interpreted awk
    – MAP
    Commented Jan 6, 2017 at 2:34

why not pipe your result to some other tools for further processing, like this:

find . -name "*.txt" -printf '%h\n'| sort | uniq | cut -d'/' -f1,2   
  • 2
    sort | uniq can be combined as sort -u which is much more efficient. And you want to do it after the cut, or you still end up with duplicates.
    – MAP
    Commented Jan 6, 2017 at 2:31
  • @MAP you are right. Commented Jan 6, 2017 at 4:50

Use sed to keep only the first directory name in the path, then sort and keep only the first line of an equal run:

find . -name "*.txt" -printf '%h\n' |
sed -e 's#^\(\./[^/]*\).*#\1#' |
sort -u

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .