Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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)
share|improve this question
1  
To help you with more than how to assign variables you might want to include your whole script. –  N.N. Feb 12 '13 at 9:48
add comment

3 Answers

up vote 1 down vote accepted

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

SNAPSHOT=SnapshotIR$TODAY*.csv

or

SNAPSHOT=SnapshotIR${TODAY}*.csv

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
share|improve this answer
add comment

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")    
snapshot=SnapshotIR$today

if [ -f ${snapshot}*.csv ]
share|improve this answer
1  
Beware that if more than one file matches ${snapshot}*.csv, all hell will break loose. –  Gilles Feb 13 '13 at 0:47
add comment
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.

SNAPSHOT=("SnapshotIR$TODAY"*.csv)

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
SNAPSHOT=("SnapshotIR$TODAY"*.csv)
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
fi
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
     SNAPSHOT=$1
  else
    echo 1>&2 "No snapshot file for $TODAY"
    exit 2
  fi
}
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:

SNAPSHOT=SnapshotIR$TODAY"*.csv
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.

share|improve this answer
    
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 '13 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. –  Gilles Feb 24 '13 at 0:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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