I'm running an expect script that takes username, password from command line.
However, password contains !! (eg: pass!!word)
But shell is expanding this to previous command (read this link)
How to escape this?
Related
I'm using Paramiko's exec_command() to run wp-cli commands on a remote server. Any command argument with spaces in it (no matter how I quote it) gives me a "Too many positional arguments" error. Here's sample code:
sshClient.exec_command("wp option update blogname \"Text with spaces\" 2>&1")
I've ssh'd into the remote machine from my local terminal and the command (wp option update blogname "Text with spaces") works fine there. I've also tried using combinations of double and single quotes.
Basically it's like the inner quotes are being ignored entirely and "Text with spaces" is being seen as 3 additional arguments. Is this about how Python parses strings with quotes, or about paramiko's exec_command()? What am I missing?
So this ended up being an issue with how the shell handles quotes in a command. Thanks to Martin for his comment pointing me in the right direction. Here is what finally worked for me:
sshClient.exec_command("wp option update blogname '\"Text with spaces\"' 2>&1")
After some Googling, I found this guide very helpful in understanding what was going on:
Shell Command Line Quoting Mechanisms
My understanding of the issue is that the shell on the remote machine where the command is being run strips out quotes, and always uses spaces as separators for arguments. So in order for "Text with spaces" to be interpreted by the remote shell as a single argument, you have to wrap it in single quotes, and escaped double quotes.
With some deeper understanding of how the shell interprets commands it makes more sense, but at face value it's not intuitive at all.
when I use zsh, exec this command as follow
$ echo "\`"
preexec: parse error
`
if change back bash, it's OK.
preexec is a hook that runs before the command: "pre-exec"ution. My hunch is you've got some prompt or zsh framework like oh-my-zsh that is choking on "`" character.
preexec
Executed just after a command has been read and is about to be
executed. If the history mechanism is active (and the line was not
discarded from the history buffer), the string that the user typed is
passed as the first argument, otherwise it is an empty string. The
actual command that will be executed (including expanded aliases) is
passed in two different forms: the second argument is a single-line,
size-limited version of the command (with things like function bodies
elided); the third argument contains the full text that is being
executed.
I'm new to unix and its developing. In my new.sh script I wrote
$USERNAME=user
$PASSWORD=sekrit
echo $USERNAME
and ran new.sh using bash new.sh
But I get the following errors
new.sh: line 1: =user: command not found
new.sh: line 2: =sekrit: command not found
How do I run that command and print the username variable in terminal?
USERNAME is the name of the variable. $USERNAME is the replacement (aka contents, aka value). Since USERNAME is empty, you effectively try to run a command named =user, which is what the error message tells you.
Remove the $ from $USERNAME=... and it will work.
As Jens notes in his answer, the problem is that an assignment to a variable is not prefixed with a $, so:
USERNAME=user
PASSWORD=sekrit
is the way to write what you wanted. You got an error because USERNAME was not set, so after expansion, the shell looked at the command as:
=user
=sekrit
and it could not find such commands on the system (not very surprisingly). However, be aware that if you have previously written:
USERNAME=archipelago
PASSWORD=anchovy
then the lines:
$USERNAME=user
$PASSWORD=sekrit
would have been equivalent to writing:
archipelago=user
anchovy=sekrit
You could see that by running set with no arguments; it would show you the values of all the variables set in the shell. You could search for words such as USERNAME and archipelago to see what happened.
Now you've learned that, forget it. The number of times you'll need to use it is very limited (but it is handy on those rare — very rare — occasions when you need it).
For all practical purposes, don't write a $ on the left-hand side of a variable assignment in shell.
When I'm interacting with the shell or writing a bash script I can do:
somecmd "some
arg"
Say now that I want to do the same in vim command-line mode:
:!somecmd "some<Enter>arg"
obviously won't work: as soon as I press <Enter> the command is executed. But neither the following do:
:!somecmd "some<C-V><Enter>arg"
:!somecmd "some<C-V>x0Aarg"
The first one inserts a carriage return instead of a line feed, which is right. The second one will break the command in two, trying to execute somecmd "some<C-V> first and then arg", both of which fail miserably.
I guess I could work around this using some echo -e command substitution, or embedding $'\n', but is it possible to type it directly in vim's command-line? I don't fully understand why the "some<C-V>x0Aarg" form doesn't work while $'some\narg' does. Is vim parsing the string previously to shell evaluation?
Well, I've found the answer myself, but I'm leaving here for further reference anyway. The documentation of :! states:
A newline character ends {cmd}, what follows is interpreted as a following ":" command. However, if there is a backslash before the newline it is removed and {cmd} continues. It doesn't matter how many backslashes are before the newline, only one is removed.
So you (I) should type "some\<C-V>x0Aarg" instead of "some<C-V>x0Aarg".
Plus, I could have done it using the system() function instead of the :! command:
:call system("somecmd 'some<C-V>x0Aarg'")
I want to run a command, for example
echo "foobar";
After each command, entered by the user.
Two scenarios:
When the user enters a command, my global command should be executed, and later his command should be executed
When the user enters a command, his command should be executed, and later my global command should be executed
How to accomplish the above two scenarios?
NB: I don't want to use the prompt for this purpose, (leave the PS1 variable as is).
As l0b0 suggests, you can use PROMPT_COMMAND to do your second request and you won't have to touch PS1.
To do your first request, you can trap the DEBUG pseudo-signal:
trap 'echo "foobar"' DEBUG
For the second part you could use declare -r PROMPT_COMMAND="echo 'foobar'": It is executed just before the prompt is displayed. Beware that it will not be run for each command in for example a pipe or command group.
Beware that any solution to this has the potential to mess things up for the user, so you should ideally only call commands which do not output anything (otherwise any output handling is virtually impossible) and which are not available to the user (to avoid them faking or corrupting the output).