Assistance with my Find command to identify last part of a file name and report the name found

Hello Forum,

We have two bootstraps of Chef in our environment which are identified by colour:

/var/chef/cache/cookbooks/bootstrap_cookbooks_version_green

and

/var/chef/cache/cookbooks/bootstrap_cookbooks_version_red

I'm attempting to identify which version is installed based on the name of the file. So far I've been able to use the following find command to help me identify the full name:

find /var/chef/cache/cookbooks/ -name "bootstrap*" -print

I think I need to redirect the result using 2>/dev/null and then pipe to use grep and identify if the filename has red or green in the name or the name isn't found.

I'd like to be able to make the report a little cleaner by reporting back if the filename had either "red" or "green" or couldn't find the file.

One more requirement is that I would like to have this command in a one liner if possible.

Thanks in advance for any advice you can provide me.

Do the two file versions coexist, or is there one single file max?
And, why a one liner? What be the benefit thereof?

2 Likes

Hello RudiC and thank you for this reply and inquiry.

The two file versions will never coexist together. It will either be:
bootstrap_cookbooks_version_green
bootstrap_cookbooks_version_red
or the file won't exist at all.

The reason for the oneliner is because I'm using a "Here Doc" in Bash to connect once to a group of servers and I'm issuing multiple commands against each server for a report. I know there are better ways to do this but this is the script we started with and what I'm supporting for now since the report from this script is actively used daily. Eventually I will move us to another way to retrieve the results we need but for now I'm keeping this script alive. So far I've been able to acheive what I need in this Here Doc step of the script whereby each data I want to retrieve from the remote server is contained all in one liner commands.

I hope this explanation is enough as to why I'm hoping I can answer this question using a one line command to identify the filename in this folder.

Thank you.

Well, then, try

TMP=$(find /where/so/ever -iname "*bootstrap*"); case ${TMP##*_} in (green) echo "is green";; (red) echo "is red";; (*) echo "is missing";; esac

You could, of course, also use grep for the same purpose.

1 Like

If you know the possible pathnames then you don't need find and grep.

if [ -f /var/chef/cache/cookbooks/bootstrap_cookbooks_version_green ]
then echo "green"
elif [ -f /var/chef/cache/cookbooks/bootstrap_cookbooks_version_red ]
then echo "red"
else echo "does not exist"
fi
1 Like

Thanks RudiC...your code worked perfectly!

Thanks for the reply MadeinGermany. I needed a one liner but I'll save your example code for future reference!

Appreciate all your help.

How about one of these two lines:

[ -f /var/chef/cache/cookbooks/bootstrap_cookbooks_version_* ] && echo /var/chef/cache/cookbooks/bootstrap_cookbooks_version_* | sed 's/.*version_//'
f=$(echo/var/chef/cache/cookbooks/bootstrap_cookbooks_version_*) && [ -f "$f" ] && echo ${f##*_} 

The second has the advantage of using POSIX shell builtin commands.

Andrew

1 Like

You can put semicolons instead of newlines.
And vice versa; there is hardly a need for a one-liner.
Example string:

echo 'two
lines'

Example shell code:

result=$(
if [ -f /var/chef/cache/cookbooks/bootstrap_cookbooks_version_green ]
then echo "green"
elif [ -f /var/chef/cache/cookbooks/bootstrap_cookbooks_version_red ]
then echo "red"
else echo "does not exist"
fi
)

Thank you apmcd47 for your helpful reply. I've managed to get the following code working to identify what I need:

[ -f /var/chef/cache/cookbooks/bootstrap_cookbooks_version_* ] && echo /var/chef/cache/cookbooks/bootstrap_cookbooks_version_* | sed 's/.*version_//'

But what could I add to this code to report that no file was found if a bootstrap_cookbooks_version_* file does not exist?

Thank you.

If you use my second example you could just add a second echo thus:

f=$(echo/var/chef/cache/cookbooks/bootstrap_cookbooks_version_*) && [ -f "$f" ] && echo ${f##*_} || echo "file does not exist"

In this case the string file does not exist is printed instead of the word red or green. Alternatively look into turning that echo into the instruction you actually want:

f=$(echo/var/chef/cache/cookbooks/bootstrap_cookbooks_version_*) && [ -f "$f" ] && cat > my_file_is_${f##*_}.txt <<EOT
this will go into the file my_file_is_red.txt
or the file my_file_is_green.txt
only if the file bootstrap_cookbooks_version_red 
(or ..._green) exist!
EOT

Andrew

This:

Is often seen but still wrong and it won't work as expected. A file glob returns a list of files (or the glob itself if no file of that pattern exists).You can't use it as input to a test -f .

Yes, test -f on wildcards is too risky.
A loop is more robust:

for f in green red; do [ -f "/var/chef/cache/cookbooks/bootstrap_cookbooks_version_$f" ] && echo "$f" && break; done || echo "file does not exist"