6

How can a command-line argument containing a dot (.) be passed? Are there any escape sequences for capturing characters like dot?

The following invocation of a bash-script from the shell does not work:

# ./deploy.sh input.txt
./deploy.sh: line 9: input.txt: syntax error in expression (error token is ".txt")

I have tried the following:

  1. backslash
  2. quote
  3. double quotes
  4. ./deploy.sh input (this works)

EDIT

Take this use-case:

  1. I have 3 files: server.jar client.jar gui.jar
  2. I need to scp them from a source to a dest
  3. source dir: login1@host1:/home/xyz/deploy/
  4. dest dir: login2@host2: /data/apps/env/software/binary/

Solution:

  1. Read artifacts to be copied into an array from the command-line
  2. create dest path and source path strings by using the correct directory prefixes
  3. use a for loop to scp each artifact (having figured out the paths)

Here's the simple script which is doing 1 (read artifacts into an array):

#!/bin/bash
declare -a artifacts
for i
do
artifacts[i]=$i
echo ${artifacts[i]}
done

Execution1

-bash-3.00$ ./simple.sh arg1 arg2 arg3
arg1
arg2
arg3

Execution2

-bash-3.00$ ./simple.sh arg1.txt arg2.txt arg3.txt
./simple.sh: line 7: arg1.txt: syntax error in expression (error token is ".txt")
10
  • 8
    There is nothing special about dots in bash; this sounds like an issue with your script deploy.sh and we would need to see it to know what it's doing and how (if at all) to change it.
    – geekosaur
    Commented May 11, 2012 at 14:31
  • 2
    You should show us deploy.sh.
    – cjc
    Commented May 11, 2012 at 14:35
  • 2
    What is line 9? :-)
    – Mikel
    Commented May 11, 2012 at 14:40
  • 4
    Woah! Put your code in the question. Makes reading it much easier.
    – Mikel
    Commented May 11, 2012 at 14:44
  • 3
    We don't need to continue in chat. You just need you to put enough information in the question so we can reproduce your problem. Which you have now done.
    – Mikel
    Commented May 11, 2012 at 15:13

2 Answers 2

10

You need to use declare -A instead of declare -a. You are clearly using associative arrays with arbitrary string arguments as indices, but declare -a is only for integer indexed arrays. arg.txt does not evaluate to a valid integer, hence your error.

Edit

You seem to be using bash version 3. Unfortunately, associative arrays are not available until version 4. I recommend you post a sanitized version of your original deploy.sh script with sensitive personal information removed so you can get ideas from other people about alternative approaches.

Edit 2

Just to summarize a bit of exchange in the chat:

The easiest way to do some action over all the arguments is to just iterate over them with a for loop:

    for arg; do
        scp login1@host1:"$arg" login2@host2:/dest/
    done

Remember to double-quote all instances of "$arg". You do not need to put the arguments in an array yourself, as they already exist in the array $@, which is what for uses by default when you don't give an explicit in list....

5

That error happens any time you try to use a string where a number was expected.

For example

$((input.txt))

will cause the same error to be printed.

In your case, it turns out you were assigning to an array which uses a numeric index.

jw013 rightly explains you need to do declare -A (uppercase A) for your example to work.

The reason why:

When assigning to an array element, you would normally write

array[0]=foo
array[1]=bar

but you can also write any arithmetic expression as the key, e.g.

array[0+0]=foo
array[1+0]=bar

so the shell is seeing

array[input.txt]=input.txt

trying to convert it to a number like

$((input.txt))

and failing.

The reason the dot is confusing and that arguments without a dot seem to work is that

$((input))

is actually a valid number.

bash sees input, decides it's a valid variable name, sees that the variable is unset, and replaces it with 0.

Compare that to input.txt, which is not a valid variable name, because variable names can't contain dots!

To avoid this confusing behavior, you can use

set -u

then any time you try to use a variable that doesn't exist, you'll get an error, e.g.

set -u
artifacts[arg1]=arg1

prints the error

scriptname: line number: arg1: unbound variable

You must log in to answer this question.

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