Suresh
Suresh

Reputation: 23

Sh command with -c option in unix

i am trying to run the below set of commands using sh -c

sh -c "
Dup_flag=`wc -l test.dat | awk '{print $1}'`;
user='[email protected]';
text='Hi';
subject='Notification';
if [ $Dup_flag -eq 0 ];
then
  echo $Dup_flag | mailx -r $user -s $subject $user;
fi
"

it is not giving the desired result

when i run the same in a script

Dup_flag=`wc -l test.dat | awk '{print $1}'`
user='[email protected]'
text='Hi'
subject='Notification'
if [ $Dup_flag -eq 8 ]
then
  echo $Dup_flag | mailx -r $user -s $subject $user
fi

it is giving the desired result

can some one help me where i am doing wrong here .i haven to run them with only sh -c

Thanks

Upvotes: 1

Views: 786

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 754570

The first version fails because the double-quoted argument is processed by the shell that invokes sh -c "…your script…".

That means that the wc and awk are run before the sh -c is invoked. Also, the various variable references $Dup_flag etc are evaluated by the invoking shell, not by the invoked shell.

You'd need to use backslashes to escape the back-ticks and dollar signs. Even if you changed to the $(…) notation, you'd still have to escape that $.

Or use single quotes around the sh -c '…your script…' and use double quotes where appropiate inside the script.

I thought I'd added the 'Escapes' and 'Single quotes' sections before. The submission process to SO glitched (paused); probably my internet connection at fault, but I seem to have closed the tab without noticing it was not successful.

Escapes

sh -c "
Dup_flag=\`wc -l test.dat | awk '{print \$1}'\`;
user='[email protected]';
subject='Notification'
if [ \$Dup_flag -eq 0 ]
then
  echo \$Dup_flag | mailx -r \$user -s \$subject \$user
fi
"

Single quotes

sh -c '
Dup_flag=`wc -l test.dat | awk "{print $1}"`
user="[email protected]"
subject="Notification"
if [ "$Dup_flag" -eq 0 ]
then
  echo "$Dup_flag" | mailx -r "$user" -s "$subject" "$user"
fi
'

Note that the single-quoted version will make it much easier to have multi-word subject lines for the email, etc.

In both versions, I deleted text as it is unused. The semicolons aren't necessary when the command is spread over multiple lines (so I removed them). They'd be necessary if it was all flattened onto a single line.


Actually, I need to run the mentioned commands in an Informatica command task which runs the commands as sh -c " my script ".

Ouch. That adds a number of levels of possible confusion. It could be that the Informatica code creates a shell command like this:

char *args[] = { "sh", "-c", your_string, 0 };
execvp(args[0], args);

In that case, my diagnosis of your problem is off the mark; nothing except the final shell interprets the contents of your string.

OTOH, they could use:

char buffer[4096];
snprintf(buffer, sizeof(buffer), "sh -c \"%s\"", your_string);
system(buffer);

In that case, the system() function runs a shell that in turn analyzes and runs the shell that actually runs your script. My analysis then comes into effect.

There are likely other ways to achieve the job; they might have subtly different effects.

Upvotes: 2

Suresh
Suresh

Reputation: 23

it worked after escaping the $ and back-ticks

sh -c "
Dup_flag=\`wc -l test.dat | awk '{print \$1}'\`
user='[email protected]';
text='Hi';
subject='Notification';

if [ \$Dup_flag -eq 8 ]
then
  echo \$Dup_flag | mailx -r \$user -s \$subject \$user;
fi
"

Thanks Jonathan

Upvotes: 1

Related Questions