I am trying to make a Bash script that would create symlinks to directories that have a “target” subdirectory. I use “find” command to search for the “target” directories and put the filepaths to array.
array_of_dirs=( $(find -type d -name "target") )
The array is looped through and symbolic links are made to directories. My issue is that the depth of the directory structure is unknown and the subdirectories can have multiple “target” directories.
The directory structure could be:
. ├── blaah │ ├── jee1 │ │ └── omg1 │ │ └── bar1 │ │ └── target <--- When this is found, no need to continue into subdirectories │ │ └── wtf1 │ │ └── target │ ├── jee2 │ │ └── target │ ├── jee3 │ └── jee4 └── blaah2 ├── jou1 │ └── target ├── jou2 └── jou3 └── target <--- When this is found, no need to continue into subdirectories ├── foo1 │ └── target ├── foo2 │ └── target └── foo3 └── target
At the moment these paths are found and there are unwanted symbolic links created.
./blaah/jee1/omg1/bar1 ./blaah/jee1/omg1/bar1/target/wtf1 <--- Unwanted ./blaah/jee2 ./blaah2/jou1 ./blaah2/jou3 ./blaah2/jou3/target/foo1 <--- Unwanted ./blaah2/jou3/target/foo2 <--- Unwanted ./blaah2/jou3/target/foo3 <--- Unwanted
How could I limit that when the “target” is found the search will not continue further into the subdirectories?
Advertisement
Answer
The shortest solution first, even if it was found at last (suggested by Eastman himself in a comment).
array_of_dirs=($(find -type d -name "foo" -prune))
With the -path option, you may exclude paths, containing the whole token “/target/”. In contrast to -name, which only evaluates the filename itself, the path needs globbing to catch foo/target and target/bar. And of course it needs negation -not -path “/target/“.
array_of_dirs=($(find -type d -not -path "*/target/*" -name "target"))
With a test on my system and foo instead of target:
find -type d -name "foo" ./tmp/bar/bar/foo ./tmp/bar/foo ./tmp/test/bar/foo ./tmp/foo ./tmp/foo/foo ./tmp/foo/foo/foo find -type d -not -path "*/foo/*" -name "foo" ./tmp/bar/bar/foo ./tmp/bar/foo ./tmp/test/bar/foo ./tmp/foo
The option -path … -prune seems to have the same effect. For detailed differences, please study the manual carefully. A short test revealed a 10% time benefit by using prune, but it can be a caching effect or random influence.
(needlessly verbose intermediate solution:)
find -type d -name “foo” -path “/foo” -prune