Home > Back-end >  Omit something from find if directory has specific file in it
Omit something from find if directory has specific file in it

Time:12-04

I need to print all my database configuration, my project uses laravel and CI framework. So in shorts I'm looking for following file.

  • .env → located at /var/www/example_system/.env
  • database.php → located at /var/www/example_system/application/config/database.php
  • core_db.php → located at /var/www/example_system/app/core/core_db.php

I'm using following find command to perform this task.

find /var/www -maxdepth 4 -type f -name ".env" -not \( -path "/var/www/*/config" -prune \) -o -path '*core/*' -name "core_db.php" -o -path '*config/*' -name "database.php"

Which print.

/var/www/baloon/app/core/core_db.php
/var/www/infinys/application/config/database.php
/var/www/duffyweb/.env
/var/www/duffyweb/config/database.php
/var/www/loseweb/.env
/var/www/loseweb/config/database.php
/var/www/resto_app/application/config/database.php

This however fails to meet my need, as it still outputting both

  • /var/www/duffyweb/config/database.php
  • /var/www/loseweb/config/database.php

even though (I thought) I already explicitly exclude it on my find command using -name ".env" -not \( -path "/var/www/*/config" -prune \) parameter.

So my question is How can I exclude something from find, if a directory has specific file in it. In this case if there was .env file, I want find to exclude config/database.php as I prioritize .env over database.php

CodePudding user response:

Let's assume example_system represents only one hierarchy level and you always want to print core_db.php if the file exists.

The following, rather complex, find command is probably not far:

find /var/www -maxdepth 4 -type f \( \
  -name .env -o -name core_db.php -o \
  -name database.php -exec sh -c '! [ -f "$(dirname "$1")"/../.env ]' _ "{}" \; \
  \) -print

The idea is to add a condition for database.php files with the -exec action. The action is a call to a sub-shell that will return true only if a file named .env does not exist two hierarchy levels under the database.php file. The sub-shell script is rather simple:

! [ -f "$(dirname "$1")"/../.env ]

It takes one argument: the path of the database.php file. It is not called directly as the -exec parameter. Instead, it is called as the script parameter of sh -c:

sh -c 'script' argv0 argv1...

argv0 corresponds to the $0 parameter of the script (unused, thus the _which I frequently use as don't-care) and argv1 corresponds to the $1 positional parameter.

But as it is a bit complex, a more straightforward bash loop may be easier to understand and maintain:

for d in var/www/*/; do 
  e="${d}.env"
  db="${d}application/config/database.php"
  c="${d}app/core/core_db.php"
  if [ -f "$e" ]; then
    echo "$e"
  elif [ -f "$db" ]; then
    echo "$db"
  fi
  if [ -f "$c" ]; then
    echo "$c"
  fi
done
  • Related