Skip to main content
added 142 characters in body
Source Link
Kamil Maciorowski
  • 75.7k
  • 22
  • 152
  • 229

There is no firm way. Only the parent shell knows the exact quoting used,used; but the parent does not have to be a shell in the first place, it can be a process that gives your script an array of arguments without parsing a representation that requires quoting or escaping. If it's a shell, there is no standard interface that would allow your script to get this information about quoting.

"The command entered by the user" may be just shell_function or ./the-script "${array[@]}", so it's not just about quoting if you want to replicate it "as precisely as possible".

If the parent shell is sophisticated enough, it may be possible to configure it beforehand, so your script can get information about the original form of the command. This would be cumbersome and shell-dependent (for a start see echo-literally here). If I was a user of your script, I wouldn't want to configure my interactive shell only to allow your script look smart.

A program in Windows can know its command string with quotes (see this other answer where it says "the situation is somewhat more complicated"), but I don't think a Bash script can use this "feature" even when started in Windows.

The best you can do is what you described:

One could check "${@}" and see which entries require escaping or quotation, but the script couldn't tell which one of the two the user used, and reproduce it.

In practice you can easily add quotes by using "${0@Q}" and "${@@Q}". Example:

foo=bar' 'baz
bash -c '
echo "You have run the following command: ${0@Q} ${@@Q}"
' "arbitrary name" arg1 arg\ 2 "arg'3"          'arg 4' "a r"\ g'\5' "$foo"

Output:

You have run the following command: 'arbitrary name' 'arg1' 'arg 2' 'arg'\''3' 'arg 4' 'a r g\5' 'bar baz'

The shell code passed after -c not only cannot tell the exact quoting used, it also cannot be aware foo was ever there.

There is no firm way. Only the parent shell knows the exact quoting used, but the parent does not have to be a shell in the first place. If it's a shell, there is no standard interface that would allow your script to get this information.

"The command entered by the user" may be just shell_function or ./the-script "${array[@]}", so it's not just about quoting if you want to replicate it "as precisely as possible".

If the parent shell is sophisticated enough, it may be possible to configure it beforehand, so your script can get information about the original form of the command. This would be cumbersome and shell-dependent (for a start see echo-literally here). If I was a user of your script, I wouldn't want to configure my interactive shell only to allow your script look smart.

A program in Windows can know its command string with quotes (see this other answer where it says "the situation is somewhat more complicated"), but I don't think a Bash script can use this "feature" even when started in Windows.

The best you can do is what you described:

One could check "${@}" and see which entries require escaping or quotation, but the script couldn't tell which one of the two the user used, and reproduce it.

In practice you can easily add quotes by using "${0@Q}" and "${@@Q}". Example:

foo=bar' 'baz
bash -c '
echo "You have run the following command: ${0@Q} ${@@Q}"
' "arbitrary name" arg1 arg\ 2 "arg'3"          'arg 4' "a r"\ g'\5' "$foo"

Output:

You have run the following command: 'arbitrary name' 'arg1' 'arg 2' 'arg'\''3' 'arg 4' 'a r g\5' 'bar baz'

The shell code passed after -c not only cannot tell the exact quoting used, it also cannot be aware foo was ever there.

There is no firm way. Only the parent shell knows the exact quoting used; but the parent does not have to be a shell in the first place, it can be a process that gives your script an array of arguments without parsing a representation that requires quoting or escaping. If it's a shell, there is no standard interface that would allow your script to get information about quoting.

"The command entered by the user" may be just shell_function or ./the-script "${array[@]}", so it's not just about quoting if you want to replicate it "as precisely as possible".

If the parent shell is sophisticated enough, it may be possible to configure it beforehand, so your script can get information about the original form of the command. This would be cumbersome and shell-dependent (for a start see echo-literally here). If I was a user of your script, I wouldn't want to configure my interactive shell only to allow your script look smart.

A program in Windows can know its command string with quotes (see this other answer where it says "the situation is somewhat more complicated"), but I don't think a Bash script can use this "feature" even when started in Windows.

The best you can do is what you described:

One could check "${@}" and see which entries require escaping or quotation, but the script couldn't tell which one of the two the user used, and reproduce it.

In practice you can easily add quotes by using "${0@Q}" and "${@@Q}". Example:

foo=bar' 'baz
bash -c '
echo "You have run the following command: ${0@Q} ${@@Q}"
' "arbitrary name" arg1 arg\ 2 "arg'3"          'arg 4' "a r"\ g'\5' "$foo"

Output:

You have run the following command: 'arbitrary name' 'arg1' 'arg 2' 'arg'\''3' 'arg 4' 'a r g\5' 'bar baz'

The shell code passed after -c not only cannot tell the exact quoting used, it also cannot be aware foo was ever there.

Source Link
Kamil Maciorowski
  • 75.7k
  • 22
  • 152
  • 229

There is no firm way. Only the parent shell knows the exact quoting used, but the parent does not have to be a shell in the first place. If it's a shell, there is no standard interface that would allow your script to get this information.

"The command entered by the user" may be just shell_function or ./the-script "${array[@]}", so it's not just about quoting if you want to replicate it "as precisely as possible".

If the parent shell is sophisticated enough, it may be possible to configure it beforehand, so your script can get information about the original form of the command. This would be cumbersome and shell-dependent (for a start see echo-literally here). If I was a user of your script, I wouldn't want to configure my interactive shell only to allow your script look smart.

A program in Windows can know its command string with quotes (see this other answer where it says "the situation is somewhat more complicated"), but I don't think a Bash script can use this "feature" even when started in Windows.

The best you can do is what you described:

One could check "${@}" and see which entries require escaping or quotation, but the script couldn't tell which one of the two the user used, and reproduce it.

In practice you can easily add quotes by using "${0@Q}" and "${@@Q}". Example:

foo=bar' 'baz
bash -c '
echo "You have run the following command: ${0@Q} ${@@Q}"
' "arbitrary name" arg1 arg\ 2 "arg'3"          'arg 4' "a r"\ g'\5' "$foo"

Output:

You have run the following command: 'arbitrary name' 'arg1' 'arg 2' 'arg'\''3' 'arg 4' 'a r g\5' 'bar baz'

The shell code passed after -c not only cannot tell the exact quoting used, it also cannot be aware foo was ever there.