5

I have a directory that contains subfolders of various depth. I want to go through all of them, check if they contain a folder with a certain name, and if that directory exists run a script (let's call this script foo.sh to avoid confusion).

foo.sh should run in the current folder if it finds the target folder. Example:

/A
  /subA-1
  /subA-2
    /target
  /subA-3
    /sub-subA-3
       /target

The command/script I'm looking for shall be ran from /A, and will then go through all subfolders looking for a folder with the name target. Upon entering /subA-2 this condition is satisfied and the foo.sh is then run in /subA-2. Same for /sub-subA-3, but not /subA-3.

foo.sh does not need any input, it just has to be run in the folder containing /target.

  • How does the script work? Does it take a directory as input? Does it need to be run from that directory? Please edit your question and clarify. – terdon Mar 1 '16 at 13:20
  • Hi, I tried to clarify the question, does that make it more clear? – snurden Mar 1 '16 at 13:27
  • Not really, you now refer to 2 scripts but only explain one of them. My question is about the script you want to run in the target directory. Does it simply run on the current directory or does it take a path as input. Have a look at my answer to see why I'm asking. – terdon Mar 1 '16 at 13:29
  • Sorry, tried again... should be more clear now. – snurden Mar 1 '16 at 13:38
  • Thanks. My answer should cover it then. I really suggest editing foo.sh, that will be simpler in the long run. – terdon Mar 1 '16 at 13:40
6

It's as simple as this:

find A -type d -name target -execdir foo.sh \;

From the man page:

-execdir command ;

Like -exec, but the specified command is run from the subdirectory containing the matched file.

Example:

Create and print the directory structure from the question:

/tmp$ mkdir A; cd A
/tmp/A$ mkdir -p subA-1 subA-2/target subA-3/sub-subA-3/target
/tmp/A$ find .
.
./subA-2
./subA-2/target
./subA-3
./subA-3/sub-subA-3
./subA-3/sub-subA-3/target
./subA-1

Now run the command, substituting pwd for foo.sh to show what's going on:

/tmp/A$ find . -type d -name target -execdir pwd \;
/tmp/A/subA-2
/tmp/A/subA-3/sub-subA-3
  • Good point! Note that not all find implementations have -execdir. It was first added in OpenBSD I believe in 1996, then eventually made it to other BSDs a few years later (1997 for FreeBSD, 2002 for NetBSD) and GNU find in 2005. – Stéphane Chazelas Mar 1 '16 at 17:15
  • Have always used this solution, however now have an AIX server with no execdir. how would I implement the similar concept without execdir ? – Victor Dec 9 at 13:38
1

With zsh:

cd /A && for dir (**/target(/N:h) (cd -- $dir && foo.sh)
1

The simplest way would be to use find to locate all directories and then modify your script to check whether a directory of the right name (foobar, for example) exists:

#!/bin/bash

targetDir="$@"   ## The directory to run the script on
dirName="target" ## Change this to whatever the "target" is
cd "$trargetDir"
## Exit if the $targetDir doesn't have a directory with 
## the name you're looking for
[ -d "$targetDir"/"$dirName" ] || exit

## If it does, cd into the $targetDir and continue the script
cd "$targetDir"

### The rest of the script goes here
...

Now, you can run a find command and have it execute your script on each directory found:

find /target -type d -exec /path/to/script.sh "{}" \; 

You could also do the whole thing with find but, personally, I find the above solution cleaner. It's up to you, however. Here's one way:

pwd="$PWD"; find . -type d -name foobar -printf '%h\0' | 
    while IFS= read -d '' dir; do cd "$dir" && foo.sh; cd "$pwd"; done
  • if foo.sh fails, cd - will not be run which would break your script. – Stéphane Chazelas Mar 1 '16 at 14:21
  • @StéphaneChazelas thanks, fixed. I guess the only safe way is to save PWD and use that. Using a ; instead of a && will still fail for cases where the cd itself fails. – terdon Mar 1 '16 at 16:28
-1

Use find command:

man find has some examples: such as

find /tmp -name core -type f -print | xargs /bin/rm -f

find . -type f -exec file '{}' \;
  • I think the problem with this is you are deleting the directories at the same time find is trying the find them – the_velour_fog Mar 1 '16 at 13:23
  • OK, and how can the OP know whether the right subdirectory exists? Your first example will just delete all matching directories, the OP wants to run a script, not just delete them. – terdon Mar 1 '16 at 13:28
  • @terdon: this is just an example of how to use the find command from the man page. The second example is likely working, by replace the file with his script. – Wei Mar 1 '16 at 13:31
  • Please read the question more carefully. Admittedly, the OP hasn't made it very clear, but they need to run their script only if a directory contains a subdirectory of a given name. In any case, copy/pasting an example from the man page isn't an answer. You need to adapt it so that it actually answers the question asked. – terdon Mar 1 '16 at 13:42

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.