How to check if busybox has a command?

1

In my case, I want to see if busybox has "md5sum" builtin.

I am currently doing this:

$ echo | busybox md5sum &>/dev/null && echo yes || echo no

I have not been able to find any information as to whether there is anything built into busybox to query what features are available programatically.

Yes, I can list the available applets by running it with no arguments, but trying to grep the output would be error prone and there is no guarantee as to whether grep will be available.

Zhro

Posted 2014-10-29T22:43:12.233

Reputation: 471

Answers

1

Thanks for the push, Micah. It got my creative juices flowing.

Updated:

Tested on Bash 3/4, all builtins, no depedencies:

Portability: 100% compatible with Bash 3 and Bash 4 only

function _busybox_has() {
   builtin command -v busybox >/dev/null ||
      return 1

   # Sanitize searches for '[' and '[['
   a=$1
   a=${a//[/\\[}

   [[ $(busybox) =~ [[:space:]]($a)([,]|$) ]] ||
     return 1
}

No bashisms, tested on Dash:

Portability: Portable on all sh with sed/egrep

_busybox_has() {
   busybox 2>/dev/null >/dev/null ||
      return 1

   # Sanitize searches for '[' and '[['
   a=$(echo $1 | sed 's/[[]/\\[/g')

   busybox | egrep -oq "[[:space:]]($a)([,]|$)" ||
      return 1
}

No bashisms, grep -e instead of egrep (more portable), tested on Dash:

Portability: Portable on all sh with sed/grep -e

_busybox_has() {
   busybox 2>/dev/null >/dev/null ||
      return 1

   # Sanitize searches for '[' and '[['
   a=$(echo $1 | sed 's/[[]/\\[/g')

   busybox | grep -oqe "[[:space:]]\($a\)\([,]\|\$\)" ||
      return 1
}

To test:

_busybox_has md5sum && echo yes || echo no

Zhro

Posted 2014-10-29T22:43:12.233

Reputation: 471

1

If I type # busybox with no parameters I get a list of configured commands that are possible.

Depending on your environment you could then parse this string. Grep is mentioned, but lacking that option, I would approach it via the string parsing tools of my environment:

bash:

options=$('busybox');

if [[ $options == *command* ]]
then
  echo "It's there!";
fi

if you're using another language there's usually something appropriate.

Micah

Posted 2014-10-29T22:43:12.233

Reputation: 36

Yes, I'm aware of that. See the last paragraph of my question. – Zhro – 2014-10-29T23:05:07.083

Fair enough. You can split by space, depending on your environment and check the list returned pretty carefully - are you writing a shell script? – Micah – 2014-10-29T23:11:09.560

This is true. But my current workaround is already slim and everything is built into bash (echo). I don't think that looping over the no-args output string would be better in this case. – Zhro – 2014-10-29T23:15:12.323

Updated with a more appropriate bash example. – Micah – 2014-10-29T23:16:25.320

*command* wouldn't be a better solution. For matching, I would need a regex, which would work, I suppose. Maybe putting it into a function like: _busybox_builtin() which returns 0/1. .. Actually, I'm am liking your idea more and more now that I'm mulling over it. I was thinking I'd need a regex lookbehind, but I'd only need to match ',' and ' '. – Zhro – 2014-10-29T23:18:07.233

Hard to know better without seeing your current solution. REGEX could work of course. I was trying to keep it simple as you're obviously in a restricted environment? – Micah – 2014-10-29T23:19:18.107

I'm expanding my personal environment by writing some portable scripts with the expectation that I will always be on at least Bash 4. – Zhro – 2014-10-29T23:20:49.813

For the impatient, here is a single-line bash script that will forcibly create all busybox symlinks. Be forewarned this will overwrite existing binaries with symlinks to busybox: for cmd in $(busybox | grep -A 30 "defined functions" | grep -v "defined functions" | tr "," "\n" | tr -d " \t" | egrep -v "^$") ; do cd /bin && ln -sf /bin/busybox ${cmd} ; done – cobbzilla – 2018-03-16T01:44:49.147