1

I am new to linux and i am writing a bash script... In the script, I have 2 variables(inside the varibles contents are there). I am trying to pass these 2 varibales in a same for loop and perform some actions.

But when i pass 2 varibles in a same for loop, am getting error. In the below code. to make it ease I am passing two paramerters but in actual it will vary. I am getting output of these varibales from a command

Below is my code:

FILES="2019_06/
2019_07/"
FILESIZE="100
200"

for file in `cat $FILES`; for filesize in `cat $FILESIZE`
 do
 do
 if [ -n "$file" ] && if [ -n "$filesize" ] 
  then
echo  $file

   curl -i -XPOST "http://localhost:8086/write?db=S3check&precision=s" --data-binary 'ecmwftrack,bucketpath=ecmwf-archive/'$file' size=$filesize'

fi
 done
done

Could any one pls help me to pass 2 arguments in the for loop at the same time.

Argument should pass like in the for loop

FILES=2019_06 FILESIZE=100
FILES=2019_07 FILESIZE=200

Below is the error message

enter image description here

Kindly help!

Below is my output

enter image description here

Below is my curl coomand

echo  curl -i -XPOST "http://localhost:xxxx/write?db=S3check&precision=s" --data-binary 'ecmwftrack,bucketpath=ecmwf-archive/'$files' size='$filesizes''


#!/bin/bash -x

# You said variables get their values from commands, so here 
# are stand-ins for those commands:
command_to_get_files(){
  aws s3 ls "s3://ui-dl-weather-ecmwf-ireland/ecmwf-archive/"| awk '{print $2}'  >>"$FILES"
}

command_to_get_filesizes(){
 for file in `cat $FILES`
 do
 if [ -n "$file" ]
  then
  # echo $file
   s3cmd du -r s3://ui-dl-weather-ecmwf-ireland/ecmwf-archive/$file | awk '{print $1}'>>"$FILESIZE"

 fi
 done
}

# I assume the values returned from the commands are whitespace delimited
# Therefore it is easy to use command substitution and transform the output
# of the commands into arrays:

files=( $(command_to_get_files) )

filesizes=( $(command_to_get_filesizes) )
clarie
  • 95
  • 2
  • 12
  • Please post the error as well – cutrightjm May 04 '20 at 05:33
  • @cutrightjm Syntax error in for loop – clarie May 04 '20 at 05:36
  • It is helpful when you ask the question to include the running of the script and the error. – cutrightjm May 04 '20 at 05:40
  • you're missing a do after the first for – pLumo May 04 '20 at 05:43
  • @pLumo I have edited the code and also posted the error message. Could u pls help me in ths – clarie May 04 '20 at 05:53
  • @cutrightjm I have posted the error message.. – clarie May 04 '20 at 05:54
  • 1
    you're missing a do after the first for – pLumo May 04 '20 at 06:01
  • 1
    Please [edit] your question to explain what you want to achieve as well how you think you should do it. Also show where your input data comes from and provide an example of it. There are already two possible answers that have been invalidated because you didn't give us the necessary detail in the question. For example, in your question you're reading data from files but in response to one answer you say the data is in environment variables. There are people who want to help you so make it easy for them to give you a plausible answer. – Chris Davies May 04 '20 at 06:52

4 Answers4

1

Here's how I'd write it:

#!/bin/bash

while read file filesize; do
  if [[ -n "$file" && -n "$filesize" ]]; then
    # This printf is a stand-in for what your really want to do
    printf "FILES=%s FILESIZE=%s\n" "$file" "$filesize"
    # I commented out the curl invocation because I don't understand it
    #curl -i -XPOST "http://localhost:8086/write?db=S3check&precision=s" --data-binary "ecmwftrack,bucketpath=ecmwf-archive/$file" size="$filesize"
  fi
done <<'EOF'
2019_06 100
2019_07 200
EOF

It reads the two variables from the heredoc that is supplied at the end.

  • In my case I have 100 parametrs and it will vary. Its not possible to give the variables at the end. – clarie May 04 '20 at 06:14
  • @clarie Beginning, end… What's the difference? Do you mean the values cannot be hardcoded in the script or what? Are they passed via already existing environment variables? What condition are you not telling us? Robin's code works for me. – Kamil Maciorowski May 04 '20 at 06:25
  • @KamilMaciorowski yes, variables are passed in the existing environment variables. We can't hardcode it – clarie May 04 '20 at 06:36
  • @KamilMaciorowski I have editied my question – clarie May 04 '20 at 06:49
0

Putting multiple values in one variable, using it unquoted and relying on word splitting to separate the values again is not a good practice. Use arrays. You can retrieve values from two or more arrays "in parallel" by using the same index; this should solve your problem.

Prepare two arrays of equal size and loop like this:

#!/bin/bash

file=( "2019_06/" "2019_07/" )
filesize=( "100" "200" )

for ((i=0; i<"${#file[@]}"; i++)) do
   echo "${file[i]}" "size=${filesize[i]}"
done

Replace echo … with the desired (and adjusted) if … curl … block.


If FILES and FILESIZE are variables through which your script receives data and you cannot change this and you must rely on word splitting, then create arrays from the variables:

file=( $FILES )
filesize=( $FILESIZE )

The variables are not quoted, word splitting (and filename generation) occurs at this stage.

  • In this case..Size is not fixed..It will vary... I think its not feasible to decleae one by one.. Could u pls help me – clarie May 04 '20 at 06:10
  • @clarie What do you mean? The loop depends on the length of the file array (${#file[@]}), so it will work for longer arrays as well. – Kamil Maciorowski May 04 '20 at 06:16
  • Yes both file and filesize will have the same length. and the loop should go through till the end – clarie May 04 '20 at 06:16
  • @clarie the loop should go through till the end – And it does. Have you tried my code with longer arrays? – Kamil Maciorowski May 04 '20 at 06:28
  • @clarie See the second part of my answer. – Kamil Maciorowski May 04 '20 at 06:53
  • yes, it worked..When i run the script in terminal i can see the output as expected.But when i use curl to insert the values in database only the first values are getting inserted 2019_06/ 100 – clarie May 04 '20 at 07:09
  • @clarie Please confirm your curl gets ${file[i]}, not just $file. Is the database able to process 100 requests almost simultaneously? – Kamil Maciorowski May 04 '20 at 07:27
  • @ Kamil Maciorowsk yes, as expected it worked in terminal..But when i substirtue in CURL its not owrking – clarie May 04 '20 at 08:27
0
#!/bin/bash

# You said variables get their values from commands, so here 
# are stand-ins for those commands:

command_to_get_files(){
  echo "2019_06/
2019_07/"
}

command_to_get_filesizes(){
  echo "100
200"
}

# I assume the values returned from the commands are whitespace delimited
# Therefore it is easy to use command substitution and transform the output
# of the commands into arrays:

files=( $(command_to_get_files) )

filesizes=( $(command_to_get_filesizes) )

# Repeat this pattern for how ever many parameters you have

# Hat tip to Kamil for idea of using arrays and C-style for loop

for ((i=0; i<"${#files[@]}"; i++)) do
    # This printf is a stand-in for what your really want to do
    #printf "FILES=%s FILESIZE=%s\n" "${files[$i]%?}" "${filesizes[$i]}"
    echo curl -i -XPOST "http://localhost:8086/write?db=S3check&precision=s" --data-binary "ecmwftrack,bucketpath=ecmwf-archive/${files[$i]%?} size=${filesizes[$i]}"
done

The percent sign question mark %? chops off the / that you didn't seem to want.

Put that in a file named myscript.sh then run it:

$ chmod +x myscript.sh
$ ./myscript.sh 
FILES=2019_06 FILESIZE=100
FILES=2019_07 FILESIZE=200

Update: Output with printf replaced by echo curl ...:

$ ./myscript.sh 
curl -i -XPOST http://localhost:8086/write?db=S3check&precision=s --data-binary ecmwftrack,bucketpath=ecmwf-archive/2019_06 size=100
curl -i -XPOST http://localhost:8086/write?db=S3check&precision=s --data-binary ecmwftrack,bucketpath=ecmwf-archive/2019_07 size=200
  • I tried the above code...As expected loop are executing twice.But Both times sames valus are coming in. 2019_06/ 100 – clarie May 04 '20 at 06:48
  • I edited my answer to show the output I get. It is not the same values repeated. – Robin A. Meade May 04 '20 at 06:51
  • yes when i run as updtaed, in the terminal values are not repaeted. But when i use curl to update in the influxdb.only first value is getting inserted. – clarie May 04 '20 at 06:59
  • I suggest you echo the curl invocation to the terminal to check it. Put echo before curl. Once you are sure the curl command looks right, remove the echo at the beginning of that line to execute curl for real. You might need to post a separate question about your curl invocation. – Robin A. Meade May 04 '20 at 07:05
  • I used echo and i also posted the output in the question sction. – clarie May 04 '20 at 07:14
  • Could u pls take alook into it – clarie May 04 '20 at 07:14
  • Your code must have a problem with the array access syntax. It's always accessing the zeroth item. Can you post your curl command? – Robin A. Meade May 04 '20 at 07:18
  • I have posted my curl commnad..Could u pls take a look n=into it – clarie May 04 '20 at 07:23
  • I replaced my printf stand-in with an echo of the curl invocation and I show the new output I get. – Robin A. Meade May 04 '20 at 07:26
  • @ Robin A. Meade ...What ever changes u made is working in the terminal. But whe n i removed printf its not inserting into the influxdb becoz it should be in single quote 'ecmwftrack,bucketpath=ecmwf-archive/'$file' size=$filesize'. But what u mentioned in your comment is in double quoye..so its failing – clarie May 04 '20 at 08:21
  • I changed the quoting slightly for the curl command. Try again. But if that doesn't work, you should post a separate question about your curl command. – Robin A. Meade May 04 '20 at 08:35
  • @ Robin A. Meade It worked, Thanks a lot...But i have one more doubt in the code. In the two functions command_to_get_files() and command_to_get_filesize() I am running commands to get the output and assign to the variable. So, in this case, $FILES will be the output of first command and $FILESIZE will be the output of second command. I need to pass $FILES as the Input to the second function in order to get the output...How to pass the varible from one function to another. – clarie May 04 '20 at 08:45
  • @ Robin A. MeadeI am posting my code in question section – clarie May 04 '20 at 08:50
0

Often you will want todo S3 stuff in parallel:

FILES="2019_06/
2019_07/"
FILESIZE="100
200"

doit() {
   s3cmd du -r s3://ui-dl-weather-ecmwf-ireland/ecmwf-archive/"$1" |
     awk '{print $1}'>>"$2"
}
export -f doit

parallel doit {1} {2} ::: $FILES :::+ $FILESISZE

Ole Tange
  • 35,514