Error in tmux's configuration file - linux

In .tmux.conf file, I have this line :
set -g status-left '#(iwgetid | cut -d '"' -f 2)'
which throws an error when I run tmux :
/home/user/.tmux.conf:8: invalid or unknown command: set -g status-left '#(iwgetid | cut -d '"' -f 2)'
The error is at the " because when I change it with a , instead, tmux doesn't throw an error. Of course, it doesn't behave as expected also.
Can someone tell me how I can solve this problem?
I already tried escaping " and ' without luck.

Start with what you want the shell to get:
iwgetid | cut -d '"' -f 2
Wrap it in #() so that it will be treated as a shell command in the expansion of status-left:
#(iwgetid | cut -d '"' -f 2)
Embed this as a string that tmux can parse. You tried to put single quotes around it:
'#(iwgetid | cut -d '"' -f 2)'
The problem is that tmux will interpret the first of the “inner” single quotes and the first of the “outer” single quotes as a single string segment, leaving the following double quote at the top-level where it now forms an unterminated string segment; the error message is not terribly clear in this situation.
To fix the problem you need to properly quote the format string (which embeds the shell command) for your chosen tmux quote characters. You might do it like this:
set -g status-left '#(iwgetid | cut -d '"'\"'"' -f 2)'
But, that is a bit hard to read, so you might consider switching your shell command to something more easily tmux-quotable:
iwgetid | cut -d \" -f 2
Which you can embed in status-left with tmux single quotes like this:
set -g status-left '#(iwgetid | cut -d \" -f 2)'
Or with tmux double quotes like this:
set -g status-left "#(iwgetid | cut -d \\\" -f 2)"
Keep in mind that tmux quoting is similar to, but not identical to Bourne-style shell quoting (e.g. top-level backslash escaping does not work the same). This quoting system is used in the config file, command-prompt (e.g. Prefix :), the confirm-before and if-shell command parameters, and the command templates for the choose- commands.

Related

Remote SSH : no such file or directory

When trying to run this cmd:
ssh user#host " cp -f /path1/`cat /path2/file.txt | awk -F : '{printf $4}' `* ../ "
got this:
cat: /path2/file.txt: no such file or directory
Notice that when execute it directly in the server it works
Thanks for any advice
Try this:
ssh user#host 'cp -f /path1/$(awk -F : '\''{printf $4}'\'' /path2/file.txt)* ..'
This might be also interesting: Useless Use of Cat Award.
Or this:
ssh user#host 'cp -f '\'"$path1"\''/$(awk -F : '\''{printf $4}'\'' /path2/file.txt)* ..'
Keep in mind:
Singe quotes do not evaluate $.
Double quotes do evaluate $.
If you want to put a single quote into a single quoted string, you have to split the string in two parts and put an escaped single quote in between. 'a'\''b' becomes a'b
If you need to evaluate a variable in a single quoted string, you have to split the string in two parts and put the double quoted variable in between. 'a'"$x"'b' becomes a${x}b

Get and use a password with special characters in Bash shell

I'm getting some troubles to use a password with special characters such as $ in a bash shell script.
My shell script is :
read -s -p "Password : " bindDNPass
ldapadd -H ldap://localhost -x -w $bindDNPass -D "dn=cn=Admin" -f /tmp/file.ldif
And the password could be something like $Something18$.
Well, the command
ldapadd -H ldap://localhost -x -W -D "dn=cn=Admin" -f /tmp/file.ldif`
asks for my $Something18$, and works fine.
But if I try
ldapadd -H ldap://localhost -x -w $Something18$ -D "dn=cn=Admin" -f /tmp/file.ldif
it doesn't work. I guess it's trying to resolve the variable $Something18, so I tried with \$Something18$, \$Something18\$, \\\$Something18$, ... but it keeps on failing...
How can I do? (Without changing my password...)
Put it in double-quotes and escape the $ symbol avoid special interpretation from the shell,
ldapadd -H ldap://localhost -x -w "\$Something18\$" -D "dn=cn=Admin" -f /tmp/file.ldif
(or) [more recommended]
Enclose it within single-quote to let the shell treat it as a literal string without expanding it,
ldapadd -H ldap://localhost -x -w '$Something18$' -D "dn=cn=Admin" -f /tmp/file.ldif
From the man bash page,
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, , \, and, when
history expansion is enabled, !. The
characters $ and retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or . A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.
I see two potential problems with how you're reading and using the password:
When you use the read command without the -r option, it'll try to interpret escape (backslash) sequences, which may cause trouble.
When you use a variable without wrapping it in double-quotes, it'll try to split the value into separate words and also try to expand any wildcards into a list of matching filenames. This can cause massive confusion, so you should almost always double-quote variable references.
Fixing these potential problems gives this script snippet:
read -rs -p "Password : " bindDNPass
ldapadd -H ldap://localhost -x -w "$bindDNPass" -D "dn=cn=Admin" -f /tmp/file.ldif
...But, while you should do both of these mods to make your script more robust, neither of these will change how it handles the password $Something18$. In fact, when I tried your original snippet with that password, it got passed to ldapadd correctly. If your actual password has some other special characters in it (or you've played with the value of IFS), these might help; otherwise, there's something else going on.
If your password still doesn't work after these fixes, try putting set -x before the ldapadd command (and set +x after) so it'll print what's actually being passed to ldapadd. Well, it'll print it in a possibly confusing form: it'll print an equivalent command to what's actually being executed, which means it'll add quotes and/or escapes to the password parameter as necessary so that you could run that command and it'll do the same thing. When I tried it with $Something18$, it printed:
+ ldapadd -H ldap://localhost -x -w '$Something18$' -D dn=cn=Admin -f /tmp/file.ldif
...where the single-quotes mean that what's inside them is passed directly, with no parsing. It could also have printed any of the following equivalent commands:
+ ldapadd -H ldap://localhost -x -w \$Something18\$ -D dn=cn=Admin -f /tmp/file.ldif
+ ldapadd -H ldap://localhost -x -w "\$Something18\$" -D dn=cn=Admin -f /tmp/file.ldif
+ ldapadd -H ldap://localhost -x -w $'$Something18$' -D dn=cn=Admin -f /tmp/file.ldif
so you have to take what it prints, and figure out how that'd be parsed by bash, in order to figure out what's actually being passed to ldapadd. But at least it'll give you some information about what's actually happening.
Oh, and you may notice that the DN argument isn't being double-quoted. That's because it doesn't contain any special characters, so the double-quotes aren't doing anything, so it just left them off.

shell bash, cat file whilst using sed to replace text

With the help of SO I have been able to correct my sed command so I can use variables (was using ' instead of " and wasn't using g for global).
However, I am struggling to get the command to work correctly.
To give you some context, I have a file containing numerous lines of text and some line contain one or more tags. these tags are in the following format:
[#$key#] - i.e #[#] is used to indicate the presence of a key
Then I have an internal array object which stores a string value which contains each key and a corresponding value in the following format:
$key=$value
What I am trying to do is to cat my file containing the tags at the same time as using a global sed replace to swap the $key for the corresponding value within the array object.
The problem I have is that my grep/sed command is not replacing any of the text and I can't figure out why.
here is my code:
for x in "${prop[#]}"
do
key=`echo "${x}" | cut -d '=' -f 1`
value=`echo "${x}" | cut -d '=' -f 2`
# global replace on the $MY_FILE
cat $MY_FILE | sed "s|\[#${key}#\]|${value}|g" > ${TEMP_MY_FILE}
cat $TEMP_MY_FILE > $MY_FILE
done
I thought about using sed -i, but my version doesn't seem to support-i
Although [ doesn't have any special meaning in a double-quoted bash string, \[ still evaluates to [ since backslashes are processed to allow for escaping dollar signs. Try
sed "s|\\[#${key}#\\]|${value}|g"
as your sed command. The double backslash will causes a literal backslash to be sent to sed, which will use it to escape the [ to treat it literally as well.

How do you quit without saving when using vim -c flag

I want to run something along the lines of
vim -r -c "w %.new | q!" ${filename}
However, the ! is parsed as the prefix for an external command. Similar issues happen when using single quotes.
I could work around this with the following code, but it feels much less clean or obvious than the previous code.
cp ${filename} ${filename}.new && mv .${filename}.swp .${filename}.new.swp;
vim -r -c "wq" ${filename}.new;
Use single quotes instead of double quotes. The ! is being interpreted in bash not vim.
vim -r -c 'w %.new | q!' ${filename}
! followed by test runs the last command that starts with that text. In this case bash looks for a command starting with " which isn't found. The single quotes stops bash from interpreting the !
Some examples of using ! in bash
It seems the actual problem was that %.new existed. To just force over write use w! instead of w
vim -r -c 'w! %.new | q!' ${filename}

Escape double quote in grep

I wanted to do grep for keywords with double quotes inside. To give a simple example:
echo "member":"time" | grep -e "member\""
That does not match. How can I fix it?
The problem is that you aren't correctly escaping the input string, try:
echo "\"member\":\"time\"" | grep -e "member\""
Alternatively, you can use unescaped double quotes within single quotes:
echo '"member":"time"' | grep -e 'member"'
It's a matter of preference which you find clearer, although the second approach prevents you from nesting your command within another set of single quotes (e.g. ssh 'cmd').

Resources