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:
- Find the directories that contain the file "password.old"
- If the directory contains "password.old" and "webvirtual" don't list them
- 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
2 Answers 2
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
.
-
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'Pietro Aretino– Pietro Aretino2017年01月25日 20:04:26 +00:00Commented Jan 25, 2017 at 20:04
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
-
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.Pietro Aretino– Pietro Aretino2017年01月25日 19:57:21 +00:00Commented 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 organizedSergiy Kolodyazhnyy– Sergiy Kolodyazhnyy2017年01月25日 20:00:31 +00:00Commented 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 itdirectory='/var/accounts/'
ordirectory='./'
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.Pietro Aretino– Pietro Aretino2017年01月25日 20:11:05 +00:00Commented Jan 25, 2017 at 20:11 -
@PietroAretino No, the variable
$directory
shouldn't be initialized. You could dofind /var/accounts/
, but originally the script is intended to be run from the directory itself, socd /var/accounts
and then run. Also, you indicated you have an older server. Do you have thedirname
command there ? It might be part of the issue. I'll edit my answer for alternative version.Sergiy Kolodyazhnyy– Sergiy Kolodyazhnyy2017年01月25日 20:16:16 +00:00Commented 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.Pietro Aretino– Pietro Aretino2017年01月25日 20:26:25 +00:00Commented Jan 25, 2017 at 20:26
[
and]
for true/false checks? How would I wrap the find command in the boolean true/false check and apply it to the variableFILE
though so I can output it to a file?