1

I need to search and find sub-directories that contain a certain file, however if they contain this certain file + this other file, I do not want them to be listed.

The statement looks something like this:

  1. Find the directories that contain the file "password.old"
  2. If the directory contains "password.old" and "webvirtual" don't list them
  3. If the directory ONLY contains "password.old" and does not contain "webvirtual" then output directory path to > OLD.TXT file

This is what I have thus far, is this totally wrong? It seems to be working correctly, but I'm fairly new to bash scripting and just wanted to make sure I'm not missing something... or maybe there's a better way to handle this?

#!/bin/sh
if FILE=$(find ./ -path OLD/ -prune -o -name "password.old") && FILE=$(find ./ -path OLD/ -prune -o -name "webvirtual*")
then
printf %"s\n" $FILE > Not_Old_Ones.txt
fi
if FILE=$(find ./ -path OLD/ -prune -o -name "password.old") && FILE=$(find ./ -path OLD/ -prune -o ! -name "webvirtual*")
then
printf %"s\n" $FILE > Old_Ones.txt
fi
3
  • Or should I be using the [ and ] for true/false checks? How would I wrap the find command in the boolean true/false check and apply it to the variable FILE though so I can output it to a file? Commented Jan 25, 2017 at 18:35
  • Where should OLD.txt be located ? In that same directory ? Commented Jan 25, 2017 at 18:37
  • Yeah where the script is ideally, or anywhere really. Commented Jan 25, 2017 at 19:54

2 Answers 2

3

I'd do:

find . -path ./OLD -prune -o -name password.old \
  ! -execdir [ -e webvirtual ] \; -printf '%h\n'

-execdir is found in GNU find (since 4.2.12 (2005)), sfind and most BSDs (where it comes from). -printf is GNU-specific. You can replace it with -execdir pwd \; for other find implementations.

If -execdir is not available:

find . -path ./OLD -prune -o -name password.old -exec sh -c '
  for file do
    dir=${file%/*}
    [ -e "$dir/webvirtual" ] || printf "%s\n" "$dir"
  done' sh {} +

The above would be POSIX. On Solaris 10 and older, be sure to use the standard sh in /usr/xpg4/bin, not the one in /bin.

1
  • Unfortunately the server I'm running this on contains an older version of find and does not understand -execdir. At least I believe that is what it is telling me. I get the error: find: invalid predicate '-execdir' Commented Jan 25, 2017 at 20:04
1

Slightly lengthy , but working solution, which should work for cases where -execdir is not available:

$ tree
.
├── dir_one
│   ├── password.old
│   └── webvirtual
└── dir_two
    └── password.old
$ find . -iname "*password.old" -exec dirname "{}" \; 2>/dev/null | while IFS= read -r directory; do
> [ -e "$directory"/webvirtual ] && continue || echo "$directory"
> done
./dir_two

Thus , all you need to do now, it add > OLD.txt at the end of the done statement to redirect output to file

In case the dirname command is not available, you can use the following script with directory as argument.

#!/bin/sh

find "$1" -type f -iname "*password.old"  -printf "%h\n" |
while IFS= read -r directory;
do
    [ -e "$directory"/webvirtual ] && continue || echo "$directory"
done

For example:

$ ./find_missing_webvirtual.sh ./TESTDIR/                                                                                
./TESTDIR/dir_two
6
  • Whoa, is the structure you're listing actually part of the script or is that just for a users sake to see what the script is doing? I've never seen something of the sort before. First time. Commented Jan 25, 2017 at 19:57
  • @PietroAretino tree is a separate command, not part of script. It's available pretty much on most Linux distros with GNU utilities. And yes, that's just for user's sake to visualize how the simple example of directories is organized Commented Jan 25, 2017 at 20:00
  • I'm surmising I must initialize $directory, as of right now the script gives me a blank file when I tried running it. However even when I give it directory='/var/accounts/' or directory='./' I am still getting a blank file. The script seems to run with no errors however. Hmm. Much appreciated none-the-less kind sir or madam. Commented Jan 25, 2017 at 20:11
  • @PietroAretino No, the variable $directory shouldn't be initialized. You could do find /var/accounts/ , but originally the script is intended to be run from the directory itself, so cd /var/accounts and then run. Also, you indicated you have an older server. Do you have the dirname command there ? It might be part of the issue. I'll edit my answer for alternative version. Commented Jan 25, 2017 at 20:16
  • Yes dirname command seems to be working. It's running CentOS 4.9. Probably why I'm having so many difficulties. Thank you for the explanation. Commented Jan 25, 2017 at 20:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .