How can I create a variable with a file name format like :

FileName pattern: SnapshotIR__somenumber.csv

I tried something like :

TODAY=$(date +"%m%d%Y")    
SNAPSHOT = $(SnapshotIR$TODAY*.csv)

I get error like :

test.sh: line 2: SnapshotIR02122013_2239.csv: command not found
test.sh: line 2: SNAPSHOT: command not found

so, when I want to use with if

if [ -f SnapshotIR$TODAY*.csv]  -> works 
if [ -f ${SNAPSHOT} ]           -> does not work (I get the above error)
  • 1
    To help you with more than how to assign variables you might want to include your whole script.
    – N.N.
    Feb 12, 2013 at 9:48

3 Answers 3

SNAPSHOT = $(SnapshotIR$TODAY*.csv)

You can't have a space in assignments. Furthermore, $(…) is a command substitution: this line attempts to execute SnapshotIR02122013_2239.csv as a program.

In bash, ksh or zsh, set SNAPSHOT to be an array containing the list of matching file names.


If there is no matching file, the pattern is left unexpanded. In bash or zsh, set the nullglob option to get an empty array instead. In ksh, put ~(N) at the beginning of the pattern (i.e. SNAPSHOT=(~(N)"SnapshotIR$TODAY"*.csv)). You can then test if there were any matching files by testing the length of the array.

shopt -s nullglob
if [ ${#SNAPSHOT} -eq 0 ]; then
  echo 1>&2 "No snapshot file for $TODAY"
  exit 2
elif [ ${#SNAPSHOT} -gt 1 ]; then
  echo 1>&2 "Multiple snapshot files for $TODAY, I don't know which one to pick"
  exit 2
echo "The snapshot file is ${SNAPSHOT[0]}"

In shells without arrays, you can use a function that receives the list of matches and counts them. If there is no match, the function receives the pattern unexpanded.

set_snapshot () {
  if [ $# -gt 1 ]; then
    echo 1>&2 "Multiple snapshot files for $TODAY, I don't know which one to pick"
    exit 2
  elif [ -e "$1" ]; then
    echo 1>&2 "No snapshot file for $TODAY"
    exit 2
set_snapshot "SnapshotIR$TODAY"*.csv
echo "The snapshot file is $SNAPSHOT"

(Note that using [ -e "$1" ] to test whether the pattern was left unexpanded fails in pathological cases such as [0-9] when there is no file whose name is a single digit but there is a file with the 5-character name [0-9]. This can't happen with only * or ? metacharacters since they match themselves.)

The following approach works to some extent:

if [ -e $SNAPSHOT ]; then …

Since the expansion $SNAPSHOT is left unquoted, it is treated as a whitespace-separated list of wildcard patterns, which is ok here. However, if there is more than one matching file, the matches will be seen as separate arguments by the [ command, and that will cause a syntax error. (With specially-crafted file names, it could even cause a wrong result.) So I don't recommend this approach, it's too brittle.

  • Thanks for showing the correct methods. First example should use ${#snapshot[@]}, ideally (( ! ${#snapshot[@]} )), though in this specific case testing the 0th element will give the illusion of working anyway.
    – ormaaj
    Feb 23, 2013 at 0:23
  • @ormaaj Right. In ksh and bash, ${#foo} is the length of the first element of the array. When dealing with an array of file names, which can't be empty, ${#foo} is 0 only if the array is empty. Feb 24, 2013 at 0:32

When you use $() shell will execute the content inside braces as command.
You're not allowed to use spaces before/after = symbol.

So your command will be as




ps. If you need to make some operations with this files in next step, it's better to use for cycle like

for file in SnapshotIR${TODAY}*.csv ; do smth ; done

cause in case you have several files matching your pattern, [ -f ${SNAPSHOT} ] contruction will return an error like:

[ -f f* ] && echo ok
-bash: [: filename: binary operator expected

Do not use spaces around = when assigning variables.

Also, I do not think you want to enclose what SNAPSHOT is assigned to in $( ) as that tries to execute it as a command.

On a side note, consider to lowercase your variables.

So what you want may be

today=$(date +"%m%d%Y")    

if [ -f ${snapshot}*.csv ]
  • 2
    Beware that if more than one file matches ${snapshot}*.csv, all hell will break loose. Feb 13, 2013 at 0:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .