My directory structure is something like below.

|- test-master-65875866-backup        
|- test-master-86565875

I tried the following code (also with double brackets)

if [ -d ${TRAVIS_REPO_SLUG#*/}-${TRAVIS_BRANCH}-*-backup ]; 
   echo "Removing previous backup"
   docker rm -f -v \$(docker ps -a -q --filter name=backup)
   sudo rm -rf ${TRAVIS_REPO_SLUG#*/}-${TRAVIS_BRANCH}-*-backup

but I'm still getting the error:

[: binary operator expected

I am wondering this error getting only in travis but not in local.

Note: ${TRAVIS_REPO_SLUG#*/} contains test and ${TRAVIS_BRANCH} contains master here.

I tried all of the following permutations but the error won't go away.

if [ -d "$TRAVIS_REPO_SLUG#*/"-"$TRAVIS_BRANCH"-*-backup ]; then

if [ -d "${TRAVIS_REPO_SLUG#*/}"-"${TRAVIS_BRANCH}"-*-backup ]; then

if [ -d "${TRAVIS_REPO_SLUG#*/}-${TRAVIS_BRANCH}-*-backup" ]; then

However the below code (with !) doesn't provide any error.

if [ ! -d ${TRAVIS_REPO_SLUG#*/}-${TRAVIS_BRANCH}-*-backup ]

Here is my complete code

  • 9
    Quote your variables. Quote your variables. Repeat after me: quote your variables. – roaima Oct 9 '18 at 10:46
  • 4
    Possible duplicate of $VAR vs ${VAR} and to quote or not to quote – roaima Oct 9 '18 at 10:49
  • 3
    Do you want to check that all the files that match "${TRAVIS_REPO_SLUG#*/}"-"${TRAVIS_BRANCH}"-*-backup are of type directory? Or that there is at least one that is of type directory? In any case [ -d file ] can take only one file, so you'll probably need a loop or a shell with glob qualifiers – Stéphane Chazelas Oct 9 '18 at 11:14
  • 1
    Call the script with bash -x to see what happens – Stéphane Chazelas Oct 9 '18 at 11:18
  • 1
    Please do what Stéphane said or if your script is too long use set -x before and set +x after the offending code and then edit your question and provide the output of your script... – Fabby Oct 9 '18 at 11:21
[ -d ${TRAVIS_REPO_SLUG#*/}-${TRAVIS_BRANCH}-*-backup ];

The unquoted * here will expand to any matching filenames

$ mkdir test-master-123-backup test-master-456-backup
$ a=test b=master
$ echo $a-$b-*-backup
test-master-123-backup test-master-456-backup

So [ gets more arguments than it expects for -d. It probably gets three in total (-d and to filenames), since that's the case where it expects the middle one to be a binary operator as the error message hints.

The version where the * is quoted shouldn't give the same error, instead it will look for a file with a literal * in the name, which is probably not what you want.

If you want to see if there are any directories matching that pattern, you could do something like this:

# set IFS to empty if you expect to have directories with whitespace in names
# IFS=''    
for f in $a-$b-*-backup; do
    if [ -d "$f" ]; then
if [ "$any" = 1 ]; then
    echo "some directories matching $a-$b-*-backup were found"

Or, in a bit simpler way in Bash. The trailing slash makes the glob only match directories, and nullglob makes the glob turn into an empty list if it doesn't match anything:

shopt -s nullglob
set -- $a-$b-*-backup/
if [ "$#" != 0 ]; then
    echo "$# directories matching $a-$b-*-backup were found"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.