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.)
The important detail here is that the kubectl ... -f
option expects a filename. If you have a file named x.yaml
, a more direct way to write what you've shown is just
kubectl replace -f x.yaml
Where you say -f -
, that ostensibly means "a file named -
", but kubectl
(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
sed 's/TAG/1.2.3-20190103/g' x.yaml | kubectl replace -f -
For Un*x tooling in general, POSIX.1 states that, for many commands,
...an operand naming a file can be specified as '-', which means to use the standard input instead of a named file....
Some commands that support this include cat, grep, sort, 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:
tar cf - . | ssh elsewhere tar xf - -C /other/dir
xargs is a tool that converts (most often) a list of filenames on standard input to command line arguments. For instance, find(1) can print a list of matching filenames to its stdout, so you could build a pipeline to delete shell backup files like
find . -name '*~' | xargs rm
You wouldn't usually use this with Kubernetes; your example tries to pass the YAML content itself as command-line arguments to kubectl
, for example. You could apply kubectl
across a directory tree with something like
find . name '*.yaml' | xargs -n1 kubectl apply -f
but since kubectl ... -f
also supports directory names (not a universal convention) you could do the same thing more directly as
kubectl apply -f . # where . is the current directory