alias in xargs sourcing tcsh - alias

I am trying to run an xargs command that uses an alias. Searching came up with this
alias gojk 'stsq \!:1 | xargs -t -0 -I {} tcsh -c source ~/.tcshrc.user;myset {}'
but it returns
Bad ! arg selector
and variations will return
source: too few arguments.

tcsh still evaluates the ! character inside of quotes. You need to put a backslash before it.
I'd suggest you make the tcsh part a script, where you pass it an argument, and get this working. Then call the script using xargs.

Use the -m flag to tcsh to have it read your ~/.tcshrc on startup, as in
... | xargs -t0 -I {} tcsh -m -c "<alias> {}"

Related

Running an awk command with $SHELL -c returns different results

I am trying to use awk to print the unique lines returned by a command. For simplicity, assume the command is ls -alh.
If I run the following command in my Z shell, awk shows all lines printed by ls -alh
ls -alh | awk '!seen[$0]++'
However, if I run the same command with $SHELL -c while escaping the ! with backslash, I only see the first line of the output printed.
$SHELL -c "ls -alh | awk '\!seen[$0]++'"
How can I ensure the latter command prints the exact same outputs as the former?
EDIT 1:
I initially thought the ! could be the issue. But changing the expression '!seen[$0]++' to 'seen[$0]++==0' has the same problem.
EDIT 2:
It looks like I should have escaped $ too. Since I do not know the reason behind it, I will not post an answer.
In the second form, $0 is being treated as a shell variable in the double-quoted string. The substitution creates an interestingly mangled awk command:
> print $SHELL -c "ls -alh | awk '\!seen[$0]++'"
/bin/zsh -c ls -alh | awk '!seen[-zsh]++'
The variable is not substituted in the first form since it is inside single quotes.
This answer discusses how single- and double-quoted strings are treated in bash and zsh:
Difference between single and double quotes in Bash
Escaping the $ so that $0 is passed to awk should work, but note that quoting in commands that are parsed multiple times can get really tricky.
> print $SHELL -c "ls -alh | awk '\!seen[\$0]++'"
/bin/zsh -c ls -alh | awk '!seen[$0]++'

remote ssh execution : Single Quotes inside double quotes

All,
I have not been able to escape single quotes while writing a file to a remote node.
ssh -i demo.pem -t ec2-user#10.10.10.10 'echo '\''{"watches": [{"type": "key","key": "test","handler": "neon -e 'sudo /opt/watch_handler.sh'"}]}'\''| sudo tee /etc/key.json'
The output I get is as follows.
{"watches": [{"type": "key","key": "test","handler": "neon -e sudo /opt/watch_handler.sh"}]}
I would like the output to have single quotes around 'sudo /opt/watch_handler.sh'
{"watches": [{"type": "key","key": "test","handler": "neon -e 'sudo /opt/watch_handler.sh'"}]}
'\' is not working.
Could you please help.
Thanks,
Getting multiple levels of quoting correct is troublesome and error-prone. Consider alternative solutions, such as:
cat <<EOF | ssh -i demo.pem -t ec2-user#10.10.10.10 sudo tee /etc/key.json
{"watches": [{"type": "key","key": "test","handler": "neon -e 'sudo /opt/watch_handler.sh'"}]}
EOF
I like using cat because it does not require any escaping to work. However, you can also generate the string locally using echo instead of cat as long as you escape the double quotes in your JSON expression:
echo "{\"watches\": [{\"type\": \"key\",\"key\": \"test\",\"handler\": \"neon -e 'sudo /opt/watch_handler.sh'\"}]}" | sudo tee /etc/key.json

output awk command result to variable

i ran the following command from console it output the correct result:0,
sudo -H -u hadoop bash -c "/home/hadoop/hadoop-install/bin/hadoop dfsadmin -report | grep 'Under replicated blocks' | awk '{print \$4}'"
however if i put it in shell script and assigned it to a variable the 'awk' won't work anymore, it just output the whole result from 'grep':
replications=`sudo -H -u hadoop bash -c "/home/hadoop/hadoop-install/bin/hadoop dfsadmin -report | grep 'Under replicated blocks' | awk '{print \$4}'"`
echo "Replications: $replications"
result: Replications: Under replicated blocks: 0
how can i make the awk work again to only output 4th column which is 0 instead of the whole string?
In backtick command substitution, \ followed by $ means just $. From the POSIX standard:
Within the backquoted style of command substitution, backslash shall retain its literal meaning, except when followed by: '$', '`', or '\' (dollar sign, backquote, backslash). (...)
With the $(command) form, all characters following the open parenthesis to the matching closing parenthesis constitute the command. Any valid shell script can be used for command, except a script consisting solely of redirections which produces unspecified results.
And yet more explicitly from the bash manpage:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.
So the easiest way is to use
replications=$(sudo -H -u hadoop bash -c "/home/hadoop/hadoop-install/bin/hadoop dfsadmin -report | grep 'Under replicated blocks' | awk '{print \$4}'")
but
replications=`sudo -H -u hadoop bash -c "/home/hadoop/hadoop-install/bin/hadoop dfsadmin -report | grep 'Under replicated blocks' | awk '{print \\\$4}'"`
also works.

Ask the compiler to ignore #pragma message

As said in the title, I want the compiler to ignore pragma message for the time being, so it's easier for me to read and fix actual warnings. I've done some searching, but there doesn't seem to be any information on it.
No it isn't possible, so the best thing to do would be to mass-edit all the #pragmas out:
$ cd MySourceFolder
$ find . -name \*.m -exec perl -p -i -n -e 's/^#pragma/\/\/#pragma/' {} \;
When you want the #pragma's back again:
$ cd MySourceFolder
$ find . -name \*.m -exec perl -p -i -n -e 's/^\/\/#pragma/#pragma/' {} \;
If you do this kind of thing alot, I would wrap that in a script, and put it into your ~/bin directory.

Scp locate's output by Xargs

I want to make a list of files of locate's output.
I want scp to take the list.
I am not sure about the syntax.
My attempt with pseudo-code
locate labra | xargs scp {} masi#11.11.11:~/Desktop/
How can you move the files to the destination?
xargs normally takes as many arguments it can fit on the command line, but using -I it suddenly only takes one. GNU Parallel http://www.gnu.org/software/parallel/ may be a better solution:
locate labra | parallel -m scp {} masi#11.11.11:~/Desktop/
Since you are looking at scp, may I suggest you also check out rsync?
locate labra | parallel -m rsync -az {} masi#11.11.11:~/Desktop/
Typically, {} is a findism:
find ... -exec cmd {} \;
Where {} is the current file that find is working on.
You can get xargs to behave similar with:
locate labra | xargs -I{} echo {} more arguments
However, you'll quickly notice that it runs the commands multiple times instead of one call to scp.
So in the context of your example:
locate labra | xargs -I{} scp '{}' masi#11.11.11:~/Desktop/
Notice the single quotes around the {} as it'll be useful for paths with spaces in them.