2

Suppose a variable value has $ symbol (storing path of a java inner class).

I want to process it as current user as well as some other user (assume current user to be root so that I need not enter password when using the su command).

Example:

path_value=/home/username/filename\$1.class

echo ${path_value}

su username -c "echo ${path_value}"

The result of first echo:

/home/username/filename$1.class

The results of the second echo inside of su command:

/home/username/filename.class

I want to use the variable such that I would be able to process it at both places with the same value.

4 Answers4

3

Export the value through the environment, then have the inner shell expand it. Assuming username's login shell is Bourne-like¹:

$ export path_value=/home/username/filename\$1.class
$ su username -c 'echo "$path_value"'
/home/username/filename$1.class

This will work even if the variable contains quotes but will not work if the command used clears the environment. I don't think su should do that, but sudo might.

If we know that the variable can't contain single quotes², then just single-quoting the expanded string in the inner shell would do:

$ path_value=/home/username/filename\$1.class
$ su username -c "echo '$path_value'"
/home/username/filename$1.class

(Note that the quotes are in the opposite order.)


¹ if username's login shell is csh or tcsh, replace echo "$path_value" with echo $path_value:q; if it's rc or derivative, with echo $path_value.

² and newline characters if the user's login shell is csh or tcsh, and that it doesn't contain bytes not forming valid characters if the user's login shell is yash. Also beware that arguments starting with - or containing backslashes would be a problem with echo, it's better to use printf '%s\n' for arbitrary data

ilkkachu
  • 138,973
  • 2
    With some su implementations and assuming the login shell of the user is Bourne-like, one can also do: su username -- -c 'printf "%s\n" "$1"' sh "$path_value" – Stéphane Chazelas Jun 27 '18 at 07:47
1

Why not use sudo instead of su?

# path_value=/home/username/filename\$1.class
# echo "${path_value}"
/home/username/filename$1.class
# sudo -u username echo "${path_value}"
/home/username/filename$1.class
Deathgrip
  • 2,566
0

in the second echo put your variable in single quotes - like:

su username -c "echo '${path_value}'"

That way echo interprets the content of the variable as a string and the "$"-sign is escaped.

rohr
  • 146
0

Remember to properly quote all expansions. The shell will not peek inside single quoted strings.

path_value='/home/username/filename$1.class'
printf '%s\n' "$path_value"

Outputs /home/username/filename$1.class.

su username -c "printf '%s\n' '$path_value'"

Identical output.

In the second command, the current shell will expand the value of path_value inside tho command, as it is double quoted. The inner printf will then print the single quoted string.

Related:


Note that ${variable} is exactly the same as $variable. Adding {...} does not quote it in any way and is only needed if the character immediately following the expansion would otherwise be taken as part of its name, as in "${variable}x".

Kusalananda
  • 333,661