4

I'm trying to figure out if there is a way to get the UNIX command tree to display only directories that match a specific pattern.

% tree -d tstdir -P '*qm*' -L 1
tstdir
|-- d1
|-- d2
|-- qm1
|-- qm2
`-- qm3

5 directories

The man page shows this bit about the switch.

-P pattern List only those files that match the wild-card pattern. Note: you must use the -a option to also consider those files beginning with a dot .' for matching. Valid wildcard operators are*' (any zero or more characters), ?' (any single character),[...]' (any single character listed between brackets (optional - (dash) for character range may be used: ex: [A-Z]), and [^...]' (any single character not listed in brackets) and|' sepa‐ rates alternate patterns.

I'm assuming that the bit about ...List only those files... is the issue. Am I correct in my interpretation that this switch will only pattern match on files and NOT directories?

2
  • 1
    what you want to accomplish ? have you tried find tstdir/ -type d -iname "qm*" or tree -I "d*" -d tstdir/ Commented Dec 21, 2012 at 20:44
  • Directories are technically also files, but a special kind of file. Commented Dec 22, 2012 at 9:22

2 Answers 2

2

There's no way for tree to do this on its own. Patterns are not applied to directories, only files.

However, you can easily accomplish what you want by getting the directory listing with tree, and then applying the match pattern with grep.

tree -d tstdir -L 1 | grep '*qm*'
3
  • This messes up the output from tree though. Commented Dec 22, 2012 at 1:02
  • @sim - In what way? Commented Dec 22, 2012 at 1:17
  • 1
    The ASCII line graphics that show the directory structure. Admittedly this isn't a huge deal but I thought I'd mention it. Commented Dec 22, 2012 at 1:20
1

Someone mentioned on stackoverflow in the trees man page that this is why the -P switch doesn't exclude things that don't match the pattern.

BUGS
   Tree  does not prune "empty" directories when the -P and -I options are
   used.  Tree prints directories as it comes to them, so  cannot  accumu‐
   late  information  on files and directories beneath the directory it is
   printing.

So it doesn't appear to be possible to get tree to filter its output using the -P switch.

EDIT #1

From a question I had posted on SO that got closed. Someone, @fhauri, had posted the following information as alternative ways to accomplish what I was trying to do with the tree command. I'm adding them to my answer here for completeness.

-d switch ask to not print files:

    -d     List directories only.

So if you WANT use this, you could:

tree tstdir -P '*qm*' -L 1 | grep -B1 -- '-- .*qm'
|-- id1
|   `-- aqm_P1800-id1.0200.bin
--
|-- id165
|   `-- aqm_P1800-id165.0200.bin
|-- id166
|   `-- aqm_P1800-id166.0200.bin
--
|-- id17
|   `-- aqm_P1800-id17.0200.bin
--
|-- id18
|   `-- aqm_P1800-id18.0200.bin
--
|-- id2
|   `-- aqm_P1800-id2.0200.bin

At all, if you use -L 1,

   -L level
          Max display depth of the directory tree.

you could better use (in bash) this syntax:

cd tstdir
echo */*qm*

or

printf "%s\n" */*qm*

and if only dir is needed:

printf "%s\n" */*qm* | sed 's|/.*$||' | uniq

At all, you could do this very quickly if pure bash:

declare -A array;for file in  */*qm* ;do array[${file%/*}]='';done;echo "${!array[@]}"

This could be explained:

cd tstdir
declare -A array          # Declare associative array, (named ``array'')
for file in  */*qm* ;do   # For each *qm* in a subdirectory from there
    array[${file%/*}]=''  # Set a entry in array named as directory, containing nothing
  done
echo "${!array[@]}"         # print each entrys in array.

... if there is no file matching pattern, result would display *. so for perfect the job, there left to do:

resultList=("${!array[@]}")
[ -d "$resultList" ] || unset $resultList

(This would be a lot quicker than

declare -A array
for file in  */*qm*; do
    [ "$file" == "*/*qm*" ] || array[${file%/*}]=''
  done
echo "${!array[@]}"

)

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.