0

I need to check if folder exist and if yes make an action or if not make another action. I use find for this task but I can't figured out the proper way:

find /path/to/destination -maxdepth 1 -type d -name "dir*" -exec bash -c '[[ $1 ]] && echo ok || echo "not ok"' _ {} \;

but or part in bash seciton is newer executed, any suggestions why ?

closed as unclear what you're asking by Jeff Schaller, roaima, Timothy Martin, G-Man, Kiwy May 16 '18 at 8:24

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Since the -exec will always pass a non-empty {}, [[ $1 ]] will always be non-null (therefore true), no? – steeldriver May 15 '18 at 15:54
  • Seems this is impossible with find ... ? – EdiD May 15 '18 at 15:57
  • 3
    You don't need the script to see if it exists; find will only find things that exist. Your [[ $1 ]] test is only checking to see if there's a string there, not "if a folder exists"; what's your real test? – Jeff Schaller May 15 '18 at 16:24
1

If you want to see if there are any directories matching that name pattern, you could have find print some dummy output for them, and see if the output was empty. E.g.:

if [[ "$(find -type d -name "dir*" -printf .)" ]] ; then
    echo "some matching directory exists"
else 
    echo "no matching directory exists"
fi

You could also have find execute a command for the files it found, by just adding the -exec bash -c '...' _ {} \; after the -printf. If the command doesn't produce any output, this should be fine.

It does get a bit worse if you need to capture output from the command started by find and keep it separate from the dummy output: you'll need temporary files or redirection trickery. This should run somecmd on any directories matched by find, directing the output of the somecmd executions to the scripts stdout, and then tell you if there were any matches.

exec 3>&1
any=$(find -type d -name "dir*" -printf . -exec bash -c 'somecmd "$1" >&3' _ {} \; )
if [[ "$any" ]] ; then
    echo "matching directories were processed"
else 
    echo "no matching directory exists"
fi
exec 3>&-

Of course, if the command started by find always produces output, there's no need the dummy output. Just capture whatever find prints, and see if it was empty.

3

The -exec will only be done for files that match the previous criteria (-name 'dir*' and -type d), and once for each file.

Here, you'd probably want to use zsh and do something like:

dirs=(/path/to/destination/dir*(N/))
if (($#dirs)); then
  echo Found these dirs:
  printf ' - %s\n' $dirs
else
  echo >&2 No dir found
fi

Or with bash version 4.4 or above and GNU find of compatible (which you must already be using as you're using the -maxdepth GNU extension):

readarray -td '' dirs < <(
  find /path/to/destination -maxdepth 1 -type d -name "dir*" -print0)

if ((${#dirs[@]})); then
  echo Found these dirs:
  printf ' - %s\n' "${dirs[@]}"
else
  echo >&2 No dir found
fi
  • I was trying to do it only with find with shortest and simplest way but seems it is not possible. – EdiD May 15 '18 at 16:00
1

It's ugly, but in bash:

(shopt -s nullglob; if ! [ -z /path/to/destination/dir*/ ] 2>&-; then  echo ok; else echo not ok; fi)

With nullglob enabled, /path/to/destination/dir*/ will expand to:

  • nothing if no matching directories were found, in which case the -z test succeeds, and so the negated test fails;
  • or to the list of all matching directories, in which case:

    • if there's only one directory, the -z test fails
    • if there are multiple directories, the test command fails since -z expects only one operand

    and so the negated test passes.

Examples:

$ if ! [ -z /a* ] 2>&-; then  echo ok; else echo not ok; fi
not ok
$ if ! [ -z /b* ] 2>&-; then  echo ok; else echo not ok; fi # multiple: /bin /boot 
ok
$ if ! [ -z /h* ] 2>&-; then  echo ok; else echo not ok; fi # single: /home
ok

This is one case where the extended test can't be used, since globbing doesn't happen in [[ ... ]].

  • 1
    Note that the expansion of /path/to/destination/dir*/ includes symlinks to directories. It's different from find's -type d or zsh's /path/to/destination/dir*(/). It's more like GNU find's -xtype d or zsh's /path/to/destination/dir*(-/). That may be just as well for the OP though. – Stéphane Chazelas May 15 '18 at 22:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.