2

On my Mac I am trying to figure out a way to check a mounted volume to a server to see if the directory receives a log file through a shell script that will be used in launchd set to a time interval.

From my searches and historically I've used:

$DIR="/path/to/file"
THEFILES=(`find ./ -maxdepth 1 -name "*.log"`)
if [ ${#THEFILES[@]} -gt 0 ]; then 
    echo "exists"
else
    echo "nothing"
fi

If the shell script is placed inside that particular directory and the files are present. However, when I move the script outside of that directory and try:

THEFILES=(`find ./ -maxdepth 1 -name "*.log"`)
cd $DIR
if [ ${#THEFILES[@]} -gt 0 ]; then 
    echo "exists"
else
    echo "nothing"
fi

I get a constant return of nothing. I thought it might be in regards to the depth so I changed -maxdepth 1 to -maxdepth 0 but I still get nothing. Through searching I ran across "Check whether a certain file type/extension exists in directory" and tried:

THEFILES=$(ls "$DIR/.log" 2> /dev/null | wc -l)
echo $THEFILES

but I'm returned a constant 0. When I searched further I ran across "Checking from shell script if a directory contains files" and tried a variation using find with:

THEFILES=$(find "$DIR" -type f -regex '*.log')
cd $DIR
if [ ${#THEFILES[@]} -gt 0 ]; then 
    echo "exists"
else
    echo "nothing"
fi

with a blank return. When I try:

if [ -n "$(ls -A $DIR)" ]; then
    echo "exists"
else
    echo "nothing"
fi

I get a blank terminal returned. On this answer I dont have prune or shopt on my Mac. So how I can I check a mounted server's directory to see if a particular file with a specific extension exists that will not give a false return from hidden files?

EDIT:

Per comment I tried removing the depth with:

THEFILES=$(find ./ -name "*.log")

but I get a blank return but if I drop a .log file in there it runs but I don't understand why else isn't returning nothing unless it's considering the hidden files. Thanks to l'L'l I learned -prune was in find's utility but when I try:

if [ -n "$(find $DIR -prune -empty -type d)" ]; then

I get a constant return of nothing when there is a LOG file present.

Community
  • 1
  • 1
DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
  • You are limiting how far the command traverses using `-maxdepth`; it sounds like this might be the issue. Also, `prune` is included in Mac's `find` utility... – l'L'l Apr 13 '17 at 22:22
  • This `find ./ -maxdepth 1 -name "*.log` searching from the _current directory_ (where the script is). If you move it outside, of course, it will not work. Use full path name, e.g. `find /full/path/name/to/dir -maxdepth.... etc` – clt60 Apr 13 '17 at 22:49
  • Maybe try like this `find "$DIR" -name "*.log" | wc -l`. Many of your commands are suppressing the output, or setup in a way that is not going to return anything. – l'L'l Apr 13 '17 at 22:49
  • I'm having trouble figuring out what you're looking for. You have the directory and you just want to see if `*.log` is present in that directory? – miken32 Apr 13 '17 at 22:54
  • @miken32 that is correct. In 5 minute intervals through an app I want to check whenever a Log file is present in the directory. – DᴀʀᴛʜVᴀᴅᴇʀ Apr 13 '17 at 22:55

2 Answers2

2

The Bash builtin compgen "displays possible completions based on the options" and is typically used for autocomplete scripts, but can be used for this purpose also. By default it outputs the completion list, so redirect it to /dev/null.

#!/bin/bash
dir=/some/log/dir
if compgen -G "$dir/*.log" > /dev/null; then
    # do stuff
fi
miken32
  • 42,008
  • 16
  • 111
  • 154
  • Interesting approach never heard or used `compgen ` before, +1 for the answer. – DᴀʀᴛʜVᴀᴅᴇʀ Apr 13 '17 at 23:13
  • 1
    That's a neat trick - I've taken the liberty to adapt it for [this answer](http://stackoverflow.com/a/35282925/45375), in the context of detecting whether a directory is empty or not (a workaround is needed to detect _hidden_ items). – mklement0 Apr 16 '17 at 04:36
1

Each of your proposed answer is really close to working!

I didn't use the -maxdepth option, if it is important to you to only check the files under $DIR but not its subdirectories, feel free to add -maxdepth 1 to any call to find.

Use lowercase variables as pointed by mklement0 to avoid conflicts with environment variables.

Answer 1

You set dir, but use ./ instead...

dir="/path/to/dir"
# Create an array of filenames
files=( $(find "$dir" -name "*.log") )
if [ ${#files[@]} -gt 0 ]; then # if the length of the array is more than 0
    echo "exists"
else
    echo "nothing"

Answer 2

You use cd $dir after running find...

dir="path/to/dir"
cd "$dir"
files=( $(find -name "*.log") )
if [ ${#files[@]} -gt 0 ]; then
    echo "exists"
else
    echo "nothing"
fi

Answer 3

you forgot a '*' before the '.log'... Have a look a the documentation for globbing

dir="/path/to/dir"
# print all the files in "$DIR" that end with ".log"
# and count the number of lines
nbfiles=$(ls "$dir/"*.log 2> /dev/null | wc -l) # nbfiles is an integer
if [ $nbfiles -gt 0 ]; then
    echo "exists"
else
    echo "nothing
fi

Answer 4

The macOS man page of find suggests that regex uses Basic Regular Expressions by default:

-E

Interpret regular expressions followed by -regex and -iregex options as extended (modern) regular expressions rather than basic regular expressions (BRE's).

You are missing a . before the * ; the cd $dir is not necessary since you pass $dir as an argument to find ; and you don't store the output of find in an array, so you can't check the length of the array.

# The output of find is stored as a string
files=$(find "/path/to/dir" -type f -regex '.*\.log')
if [ -n "$files" ]; then # Test that the string $files is not empty
    echo "exists"
else
    echo "nothing"
fi
silel
  • 567
  • 2
  • 10