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? Jan 25 '17 at 18:35
  • Where should OLD.txt be located ? In that same directory ? Jan 25 '17 at 18:37
  • Yeah where the script is ideally, or anywhere really. Jan 25 '17 at 19:54
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. Jan 25 '17 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 Jan 25 '17 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. Jan 25 '17 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. Jan 25 '17 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. Jan 25 '17 at 20:26
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' Jan 25 '17 at 20:04

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.