0

Problem:

I need to send a command to a named pipe and need to ensure only the command is sent and not any errant or "fat-fingered" characters.

Example:

I have been using the following:

echo "command" > /path/to/namedPipe

This works fine, but I noticed something odd, that it is possible to send errant keystrokes to the pipe. For example:

echo "command" > /path/to/namedPipe straycharacters

then both <command> and <straycharacters> are written to namedPipe. I would not have guessed this would happen, but in some cases it can really mess up my program. I also noticed echo does not seem to require quotes. My command does not require quotes, just the actual <command>. What would be the best practice to write only <command> to the pipe?

Possible Solution:

printf "command" > /path/to/namedPipe straycharacters

In my terminal this only prints out <command> and not <straycharacters>, and so far it appears to be compatible with my program. However it is a little different than echo because it seems to not include a new line.

  • 2
    That's because the first argument to printf is a format string. If it contained %s, %d, etc., the remaining arguments will be printed accordingly. How do you guarantee you won't fat finger the first argument? – muru Jun 13 '19 at 04:29
  • Use single quotes rather than double quotes, it means that dollar is not special so one less thing to fat finger. However reading the fine manual is always a good idea. – icarus Jun 13 '19 at 04:36

1 Answers1

2

This command

echo "command" > /path/to/namedPipe straycharacters

is equivalent to

echo "command" straycharacters >/path/to/namedPipe

(compare this) and echo prints all its operands, so in this case straycharacters as well. Similarly your "working" solution is equivalent to

printf "command" straycharacters >/path/to/namedPipe

and it "works" only because

  • command apparently doesn't include fragments that would be interpreted by the shell in a non-literal fashion (like ${PATH});
  • command apparently doesn't include fragments that would be interpreted by printf in a non-literal fashion; note command is interpreted as format (see man 1 printf for details); if there was %s there, straycharacters would be substituted.

The right way to pass command (and a newline) is

printf '%s\n' 'command' >/path/to/namedPipe    # straycharacters

where

  • \n is responsible for printing a newline character;
  • straycharacters appear in the comment;
  • all strings that should should be passed to printf literally are single-quoted (although you may want to double-quote command, e.g. if it relies on parameter substitution by design).

Having "errant or fat-fingered characters" in your code is wrong. Instead of trying to find syntax that ignores them, just remove this garbage and pay attention. This will make your code clean and nice.

Still, even without straycharacters, echo is not a right tool. See Why is printf better than echo?

  • Awesome, thanks, now I understand printf. In my case I can just use '%s' and do not need the \n because I want to make sure junk typed after namedPipe is not passed in. I am actually running the command as an exec node in nodeRed and (it's probably something dumb I am doing) but the symptom is that extra junk is appended after namedPipe and that kills my program. So I do not want a comment or strayCharacters and I'm trying to make sure command and ONLY command is what the program receives. – cuxcrider Jun 13 '19 at 06:45
  • After some further testing I see what you mean about the #. It will truly block any extra characters. And with the \n it is working great so far. So in nodeRed I issue the command at the exec node like this: printf '%s\n' 'command' >~/namedPipe # and if for whatever reason extra junk is appended it will simply be seen as a comment. I wish I could log what the actual command sent to the pipe is but I have not figured that out yet. – cuxcrider Jun 13 '19 at 13:23