1

On my CentOS 7 machine, I have a folder which contains 2 files, with names like:

myapp-nightly__v3.0-SNAPSHOT__b59__lite.zip
myapp-nightly__v3.0-SNAPSHOT__b59.zip

These files are erased and generated every night, and the number after the "b" (in the example above, 59), is incremented.

I want to have a bash script file, in which I can get, in a variable, the name of the file that doesn't contain "_lite" in it (in the example above, that would be "myapp-nightly__v3.0-SNAPSHOT__b59.zip")

So, I first tried "ls" with globbing in a terminal, to see how that works:

ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip

This correctly outputs "myapp-nightly__v3.0-SNAPSHOT__b59.zip".

Then I tried making a simple bash script, that runs the above command, and stores its output in a variable:

#!/bin/bash
MYAPP_KIT_FULL_PATH=$(ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)
echo "MYAPP_KIT_FULL_PATH=$MYAPP_KIT_FULL_PATH"

This gives me the following error:

./test.sh: command substitution: line 3: syntax error near unexpected token `('
./test.sh: command substitution: line 3: `ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)'

So my question is, how do I correctly execute such a "ls" command in a bash script, and store its output in a variable? Does this not work in bash because of the glob characters?

Extra remarks:

  • I know the error message says "line 3" but I'm pretty sure it refers to line 2 (line 3 just does an echo). Even if I completely erase line 3 from the script (so that the script only has 2 lines), it still gives the error about line 3
3
  • 1
    what do you want to do after you get those files? btw, using ls to get file in script is not recommended Commented Dec 13, 2018 at 10:20
  • after i get the filename, i want to unzip it. So i want to do "unzip $MYAPP_KIT_FULL_PATH" Commented Dec 13, 2018 at 10:23
  • That looks like an extended glob (wildcard) expression, but the error indicates you don't have extended globs enabled. You can add shopt -s extglob at the beginning. But also, you really shouldn't parse the output of ls. Commented Dec 13, 2018 at 16:55

2 Answers 2

3

You could use find :

find dir -maxdepth 1 -name 'myapp-nightly__v3.0-SNAPSHOT__b*.zip' -not -name '*lite.zip'

To unzip the target file in your current directory :

find dir -maxdepth 1 -name 'myapp-nightly__v3.0-SNAPSHOT__b*.zip' -not -name '*lite.zip' -exec unzip {} \;
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, this works great. So instead of "dir" i specify the actual folder where these files are located.
Exactly ! You can use . if you're already in the directory that contain the files.
Careful; if there are subdirectories, this will search all of them for matching files as well (and try to operate on any it finds). I'd add a -maxdepth 1 restriction in there.
1

You're using an extended glob (wildcard) expression, but the error indicates you don't have extended globs enabled. You can add shopt -s extglob at the beginning. But also, you really shouldn't parse the output of ls.

There are several options for doing this "right" in bash. @Aaron's already shown how to use find, so I'll give a couple of pure-bash options. First, you can just use a bare wildcard expression (no ls) and capture the result to an array:

#!/bin/bash
shopt -s extglob
myapp_kit_full_paths=(myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)
# Operate on just the first match:
unzip "${myapp_kit_full_paths[0]}"
# Operate on *all* matches (in case there are several):
for file in "${myapp_kit_full_paths[@]}"
    unzip "$file"
done

(BTW, note that I used a lowercase variable name here. There are a bunch of all-caps names with special meanings, and using one of those by accident can cause trouble; therefore, lower- and mixed-case variable names are safer for your own purposes.)

Another option is to just expand the glob expression directly in a for statement:

#!/bin/bash
shopt -s extglob
for myapp_kit_full_path in myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip
    unzip "$myapp_kit_full_path"
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.