2

I would like to add:

function ps_mem {
   python /home/vagrant/ps_mem/ps_mem.py -p $@
}

To the end of ~/.bashrc from the command-line. I have tried using:

printf "function ps_mem {\n python /home/vagrant/ps_mem/ps_mem.py -p $@ \n}" >> ~/.bashrc

And while it almost worked, the input field $@ was ignored, making this:

function ps_mem {
 python /home/vagrant/ps_mem/ps_mem.py -p
}

Instead, be added to the end of ~/.bashrc.

chaos
  • 48,171
Josh Pinto
  • 3,493
  • 2
    "'$@'" would do it... But you want "'"$@"'" so that you have quotes in the function. – jasonwryan Oct 27 '15 at 07:11
  • That looks more like a mix between a ksh script (function foo { syntax) and zsh script ($@ unquoted which only makes sense in zsh and is for the list of non-empty arguments) than a bash script. In bash, that would be ps_mem() { python /home/vagrant/ps_mem/ps_mem.py "$@"; } or if you do really want to remove empty arguments: ps_mem() (IFS=; set -f; python /home/vagrant/ps_mem/ps_mem.py $@;} – Stéphane Chazelas Oct 27 '15 at 08:55

4 Answers4

5

Use a here document for such jobs:

cat <<'EOF' >>~/.bashrc
function ps_mem {
   python /home/vagrant/ps_mem/ps_mem.py -p "$@"
}
EOF

Special characters inside a here document will not be expanded by the shell when <<'EOF' is quoted. From POSIX Shell Command Language:

If any character in word is quoted, [...] the here-document lines shall not be expanded.

chaos
  • 48,171
  • special chars will be expanded by the shell in a here doc. that's part of the point of them, simple templating. Use python ... "\$@" instead, otherwise "$@" will be expanded to the args of the current running script. – cas Oct 27 '15 at 07:22
  • 1
    @cas Sorry, forgot to add quotes in word. They will not be expanded now. – chaos Oct 27 '15 at 07:34
  • yep, that's right. +1 – cas Oct 27 '15 at 07:41
3

The printf in the original question works if you replace the double quotes " with single quotes.

I like to use printf this way. No special quoting rules as in here documents. And no thinking about \n. What you see is what you get:

printf '%s' '
function ps_mem {
   python /home/vagrant/ps_mem/ps_mem.py -p "$@"
}
' >> ~/.bashrc
RobertL
  • 6,780
  • 1
    To echo and "what you see is what you get" -> http://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo/65819#65819 – chaos Oct 27 '15 at 08:22
  • RobertL, echo is only good for fixed text. printf is actually extremely simple and I urge you to learn it. – Wildcard Oct 27 '15 at 08:26
  • @chaos I don't think that information applies specifically to this answer, if you know different, please respond. Howerver, in the interest of overall good practice, I'm changing echo to printf, and will begin to use printf more often because it seems it's now widely supported (which has not always been true, depending how far back in time you go. – RobertL Oct 27 '15 at 08:48
  • 1
    It applies as soon as you have uncontrolled data -> a variable for example $@. But now it should be more reliable +1 – chaos Oct 27 '15 at 08:50
  • 1
    Better as printf %s '....' so as not to have to worry whether the text contains backslash or percent characters or not. – Stéphane Chazelas Oct 27 '15 at 08:51
  • @chaos There is no uncontrolled data in this example, therefore the info does not apply. Using printf vs echo does not change the reliability of this specific code. – RobertL Oct 27 '15 at 08:58
  • @stéphane-chazelas Good point, and also illustrates changing good code because of dogmatism is also hazardous. – RobertL Oct 27 '15 at 08:59
  • @Wildcard Believe me, I know printf, and write, print/println, iostreams, python %, etc etc. The main point of this example is that if you have static, pre-formatted text, often the best way to represent that in the shell is within a multi-line single-quoted string. – RobertL Oct 27 '15 at 09:04
2

Other answers have been given which will work, but in the spirit of helping you do it exactly the way you were trying to (since it's a totally fine way to do it):

Here is the original:

printf "function ps_mem {\n python /home/vagrant/ps_mem/ps_mem.py -p $@ \n}" >> ~/.bashrc

Here is a version that works:

printf 'function ps_mem {\n python /home/vagrant/ps_mem/ps_mem.py -p $@ \n}' >> ~/.bashrc

I recommend adding double quotes around $@ also:

printf 'function ps_mem {\n python /home/vagrant/ps_mem/ps_mem.py -p "$@" \n}' >> ~/.bashrc

Variable expansion is enabled in double quotes; disabled in single quotes.

Wildcard
  • 36,499
0

To get your desired output you can use escape sequence like so

  python /home/vagrant/ps_mem/ps_mem.py -p \$@ 
monirz
  • 101