2

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)

./out/data
./out/data
./output/data

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

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 Jan 6 '17 at 2:19
  • @Sigur my gut says the second, but I'd have to benchmark them to say for sure – Eric Renouf Jan 6 '17 at 2:22
  • What do you think about awk -F'/' '{print $1"/"$2}'. It is simpler, I think. – Sigur Jan 6 '17 at 2:24
  • 1
    @Sigur it's simpler, but won't remove duplicates – Eric Renouf Jan 6 '17 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 Jan 6 '17 at 2:34
1

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 Jan 6 '17 at 2:31
  • @MAP you are right. – David Dai Jan 6 '17 at 4:50
1

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

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.