0

I am using the bash -c command and a function:

fun ()
{
echo "$0"  ## it reads the parameter $i
}

for i in {1..5}
do
bash -c "fun" $i &
done

My question is can we pass multiple parameters to function by using bash -c? for example:

fun ()
{
echo "$0"  ## it reads the parameter $i
}

var="string"  #variable

for i in {1..5}
do
bash -c "fun" $i $var &
done
  • Assuming you're running your program in BASH (please confirm it), why do you need bash -c? Why not simply fun $i? – Quasímodo Feb 7 at 13:16
  • @quasimodo, when ever i do fun $i & run in background for multiple inputs, the $$(which is in the function) returns the same value, but when I use bash -c the $$(in the function) workes gives the diff values. thats why i am using the bash -c – sai prudhvi Feb 7 at 16:10
  • Use $BASHPID and stop this bash -c nonsense. – Kamil Maciorowski Feb 7 at 16:34
3

Have you actually run the code? Both snippets return fun: command not found and this is the problem you need to address first.

Unless you managed to export fun as a function, or defined it elsewhere in a way that allows the inner bash to recognize the command (I will not elaborate). This situation would be quite misleading, thus unfortunate in the context of further issues.

Let's start with straightforward code that does what you probably wanted:

#!/bin/bash

fun ()
{
   echo "$1"
}

for i in {1..5}
do
   fun "$i" &
done

If you get numbers not in sequence, it's because of &. I used & here because it was in your original code.

Your definition of the function is syntactically OK. My definition uses $1 instead of $0, we'll get to it. To use a function you just call its name, with or without arguments. In our case:

fun
fun arg1
fun arg1 arg2

Inside a function $1, $2, … expand to respective arguments. You use $@ (or $* if you know what you are doing) to get all the arguments. You use $# to get the number of arguments. This is very similar to a situation where fun is a shell script.

$0 inside a function is $0 of the main shell. It has nothing to do with arguments passed to the function.

You can run the function in a subshell:

( fun arg1 )

or in the background (which implicitly runs it in a subshell as well):

fun arg1 &

If fun is a function in the main shell then these subshells will also know what to do when the command is fun. On the other hand a shell started with bash -c has no idea of fun.

Again: unless you managed to export … or …

In your case bash -c is rather an obstacle. I see no point in using it. It is possible to make it work but it would be cumbersome. Still, your explicit question is:

can we pass multiple parameters to function by using bash -c?

We can. Cumbersome example below. Note the function is slightly different (for educational reason). I also dropped & because it only obfuscates the results.

#!/bin/bash

fun ()
{
   echo "$2"
}

export -f fun
var="string"

for i in {1..5}
do
   bash -c 'fun "$2" "$1"' inner-bash "$i" "$var"
done

Exporting a function from Bash to Bash is possible and we just did it. Exporting a function from Bash to another shell is impossible, unless the shell tries to be compatible and deliberately interprets some environment variables as functions.

fun "$2" "$1" is single-quoted, so in the main shell "$2" and "$1" are not expanded (being single-quoted, they are not double-quoted). In the context of the inner bash these $2 and $1 are double-quoted and they expand to parameters provided after inner-bash (which is an arbitrary name here).

See what happens to a number stored as $i:

  • it's $i in the context of the main shell;
  • then it's $1 in the context of the inner shell;
  • then it's $2 in the context of the function in the inner shell.

There is no advantage of using bash -c here, only inconvenience. Do not complicate your code this way.

One more thing: double-quote variables.

| improve this answer | |
  • thank you for valuable answer, I am using $0 because bash -c takes from 0th value instead of 1st value that we are passing. – sai prudhvi Feb 7 at 16:25
  • I asked this sample question because in my actual script I am runing the function 8 times(in a loop for diff files) and we will have 8 different subshells, so i am using bash -c. – sai prudhvi Feb 7 at 16:29
  • @saiprudhvi From 0th for good reason. See man 1 bash where it describes -c. $0 is "used in warning and error messages". Suppose you want to pass the string date. Invoke bash -c 'nonexistent "$1"' my_bash date; The error is my_bash: nonexistent: command not found. You know at once the problem is with my_bash. Invoke bash -c 'nonexistent "$0"' date; the error is date: nonexistent: command not found. It suggests date may be the command that is not found; and you wonder where the error came from. Therefore use some name to populate $0 and provide actual arguments after it. – Kamil Maciorowski Feb 7 at 17:06
  • @saiprudhvi It will be even worse if instead of a fixed string (like date) you provide an expanded variable. You may get errors (or warnings) starting from "random" strings that make absolutely no sense in errors. Very confusing. Your original code yields not only fun: command not found but like 1: fun: command not found or 5: fun: command not found. It's because $i from the main shell becomes $0 in the inner shell. – Kamil Maciorowski Feb 7 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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