<p>I'm daily user of kubectl, but not expert of linux. Recently I need edit some service type after deployment, so searched and used kubectl <a href="https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#replace" rel="noreferrer">replace</a> and it worked well.</p>

<pre><code>cat yaml | kubectl replace -f -

service/tracs-pool-1sv replaced
</code></pre>

<p>But I don't understand why add <strong>a short dash</strong> <code>-</code> at the last.
The doc only says:</p>

<blockquote>
  <p>Replace a pod based on the JSON passed into stdin.</p>
</blockquote>

<p>I searched and found <a href="https://stackoverflow.com/questions/35116699/piping-not-working-with-echo-command">this</a> SO question, and learned kubectl command may be that kind of command that <strong>does not read stdin</strong>(am I right?).</p>

<p>I tried</p>

<pre><code>cat yaml |xargs kubectl replace -f
</code></pre>

<p>but error returned:</p>

<pre><code>the path "apiVersion:" does not exist
</code></pre>

<p>So is the ending short dash(-) syntax built for kubectl <strong>ONLY</strong>? or is some more <strong>common</strong> syntax of linux bash stdin pipe? 
Can some one explain why xargs not work here and I must place a short dash(-) at the end?</p>

Lei Yang
<p>This is a reasonably common, but not universal, Un*x convention.  (It is mentioned in the POSIX specification and so most non-Linux Unices will support it as well.)</p>

<p>The important detail here is that the <code>kubectl ... -f</code> option expects a <em>filename</em>.  If you have a file named <code>x.yaml</code>, a more direct way to write what you've shown is just</p>

<pre class="lang-sh prettyprint-override"><code>kubectl replace -f x.yaml
</code></pre>

<p>Where you say <code>-f -</code>, that ostensibly means "a file named <code>-</code>", but <code>kubectl</code> (along with many other tools) actually interprets this to mean "the process's standard input".  For instance, you could use this for a very lightweight templating system, like</p>

<pre class="lang-sh prettyprint-override"><code>sed 's/TAG/1.2.3-20190103/g' x.yaml | kubectl replace -f -
</code></pre>

<p>For Un*x tooling in general, <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_04" rel="noreferrer">POSIX.1 states</a> that, for many commands,</p>

<blockquote>
  <p>...an operand naming a file can be specified as '-', which means to use the standard input instead of a named file....</p>
</blockquote>

<p>Some commands that support this include <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cat.html#tag_20_13" rel="noreferrer">cat</a>, <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html#tag_20_55" rel="noreferrer">grep</a>, <a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html#tag_20_119" rel="noreferrer">sort</a>, and tar (not required by POSIX).  One way to move a directory tree between two Linux machines, for instance, is to create a tar file on stdout, pipe that stream via ssh to a remote machine, and then unpack the tar file from stdin:</p>

<pre class="lang-sh prettyprint-override"><code>tar cf - . | ssh elsewhere tar xf - -C /other/dir
</code></pre>

<p><a href="http://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html#tag_20_158" rel="noreferrer">xargs</a> is a tool that converts (most often) a list of filenames on standard input to command line arguments.  For instance, <strong>find</strong>(1) can print a list of matching filenames to its stdout, so you could build a pipeline to delete shell backup files like</p>

<pre class="lang-sh prettyprint-override"><code>find . -name '*~' | xargs rm
</code></pre>

<p>You wouldn't usually use this with Kubernetes; your example tries to pass the YAML content itself as command-line arguments to <code>kubectl</code>, for example.  You could apply <code>kubectl</code> across a directory tree with something like</p>

<pre class="lang-sh prettyprint-override"><code>find . name '*.yaml' | xargs -n1 kubectl apply -f
</code></pre>

<p>but since <code>kubectl ... -f</code> <em>also</em> supports directory names (not a universal convention) you could do the same thing more directly as</p>

<pre class="lang-sh prettyprint-override"><code>kubectl apply -f . # where . is the current directory
</code></pre>
