1

Dipping my toes into Bash coding for the first time (not the most experienced person with Linux either) and I'm trying to read the version from the version.php inside a container at:

/config/www/nextcloud/version.php

To do so, I run:

docker exec -it 1c8c05daba19 grep -eo "(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?" /config/www/nextcloud/version.php 

This uses a semantic versioning RegEx pattern (I know, a bit overkill, but it works for now) to read and extract the version from the line:

$OC_VersionString = '20.0.1';

However, when I run the command it tells me No such file or directory, (I've confirmed it does exist at that path inside the container) and then proceeds to spit out the entire contents of the file it just said doesn't exist?

grep: (0|[1-9]\d*).(0|[1-9]\d*).(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-])(?:.(?:0|[1-9]\d|\d*[a-zA-Z-][0-9a-zA-Z-]))))?(?:+([0-9a-zA-Z-]+(?:.[0-9a-zA-Z-]+)*))?: No such file or directory /config/www/nextcloud/version.php:$OC_Version = array(20,0,1,1); /config/www/nextcloud/version.php:$OC_VersionString = '20.0.1'; /config/www/nextcloud/version.php:$OC_Edition = ''; /config/www/nextcloud/version.php:$OC_VersionCanBeUpgradedFrom = array ( /config/www/nextcloud/version.php: 'nextcloud' => /config/www/nextcloud/version.php: 'owncloud' => /config/www/nextcloud/version.php:$vendor = 'nextcloud';

Anyone able to spot the problem?

Update 1:

For the sake of clarity, I'm trying to run this from a bash script. I just want to fetch the version number from that file, to use it in other areas of the script.

Update 2:

Responding to the comments, I tried to login to the container first, and then run the grep, and still get the same result. Then I cat that file and it shows it's contents no problem.

enter image description here

2
  • docker exec -it command is used to login to the container and once you login then you can grep. so, first login to the container docker exec -it 1c8c05daba19 and then search with regexp Commented Oct 30, 2020 at 8:05
  • hmm , login into the container, check if the file exists, try to run the bash after you login, check if it working fine. 99% you may have made a simple mistake Commented Oct 30, 2020 at 10:33

2 Answers 2

2

Many containers don't have the GNU versions of Unix tools and their various extensions. It's popular to base containers on Alpine Linux, which in turn uses a very lightweight single-binary tool called BusyBox to provide the base tools. Those tend to have the set of options required in the POSIX specs, and no more.

POSIX grep(1) in particular doesn't have an -o option. So the command you're running is

grep \ -eo \ # specify "o" as the regexp to match "(regexps are write-only)" \ # a filename /config/www/nextcloud/version.php # a second filename 

Notice that the grep output in the interactive shell only contains lines with the letter "o", but not for example the line just containing array.

POSIX grep doesn't have an equivalent for GNU grep's -o option

Print only the matched (non-empty) parts of matching lines, with each such part on a separate output line. Output lines use the same delimiters as input....

but it's easy to do that with sed(1) instead. Ask it to match some stuff, the regexp in question, and some stuff, and replace it with the matched group.

sed -e 's/.*\(any regexp here\).*/\1/' input-file 

(POSIX sed only accepts basic regular expressions, so you'll have to escape more of the parentheses.)

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @David Maze, I had also thought of checking the version of grep inside the container just before reading your post and did a quick grep --help. And you're right, it uses a slimmed down busybox version that also looks like it needed a -f argument for the filename, but oddly, it does still have the -o argument. i.imgur.com/hKqEkei.png I still can't get it working though, so I'll give your sed suggestion a shot.
Does this look right? sed -e 's/.*\([0-9]{1,2}\)+[.]+\([0-9]{1,2}\)+[.]+\([0-9]{1,2}\).*/\1/' /config/www/nextcloud/version.php. Trying a different regex, but when I use it, it just echos back the entire contents of the file.
Same result with more escaped chars: sed -e 's/.*\([0-9]\{1,2\}\)\+[.]\+\([0-9]\{1,2\}\)\+[.]\+\([0-9]\{1,2\}\).*/\1/' /config/www/nextcloud/version.php
0

Well, for any potential future readers, I had no luck getting grep to do it, I'm sure it was my fault somehow and not grep's, but thanks to the help in this post I was able to use awk instead of grep, like so:

docker exec -it 1c8c05daba19 awk '/^\$OC_VersionString/ && match($0,/\047[0-9]+\.[0-9]+\.[0-9]+\047/){print substr($0,RSTART+1,RLENGTH-2)}' /config/www/nextcloud/version.php 

That ended up doing exactly what I needed:

  • It logs into a docker container.
  • Scans and returns just the version number from the line I am looking for at: /config/www/nextcloud/version.php inside the container.
  • Exits stage left from the container with just the info I needed.
  • I can get right back to eating my Hot Cheetos.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.