简体   繁体   中英

What does the following bash command mean?

The command-

(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)

How this command is explained in the documentation-

(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xpvf -)
# Move entire file tree from one directory to another
# [courtesy Alan Cox <a.cox@swansea.ac.uk>, with a minor change]

# 1) cd /source/directory
#    Source directory, where the files to be moved are.
# 2) &&
#   "And-list": if the 'cd' operation successful,
#    then execute the next command.
# 3) tar cf - .
#    The 'c' option 'tar' archiving command creates a new archive,
#    the 'f' (file) option, followed by '-' designates the target file
#    as stdout, and do it in current directory tree ('.').
# 4) |
#    Piped to ...
# 5) ( ... )
#    a subshell
# 6) cd /dest/directory
#    Change to the destination directory.
# 7) &&
#   "And-list", as above
# 8) tar xpvf -
#    Unarchive ('x'), preserve ownership and file permissions ('p'),
#    and send verbose messages to stdout ('v'),
#    reading data from stdin ('f' followed by '-').
#
#    Note that 'x' is a command, and 'p', 'v', 'f' are options.
#
# Whew!

There are a couple of things which I don't understand in the explanation given above-

  • In the 3rd step it states f - designates the target file as stdout, but there is nothing in output right now, while creating archive, from where is the name of file supplied?
  • In the 8th step it states, it reads data from stdin, but I didn't give any input, is there any input left in the stream?

This command works fine but I am a little confused on how it works. Any help will HELP.

Edit- The link to this, scroll a bit down you will find it.

The explanation you quoted from the code is remarkably good. I wish every script I read (or wrote.) was documented so well.

In the 3rd step it states f - designates the target file as stdout, but there is nothing in output right now, while creating archive, from where is the name of file supplied?

There is no file name. The archive data are written to stdout, the process's standard output stream. If that were not piped into another program then it would be displayed on the screen.

In the 8th step it states, it reads data from stdin, but I didn't give any input, is there any input left in the stream?

The output (to its stdout) of the first tar command is piped into (the stdin of) the second tar command, as mentioned at step 4 of the documentation. You can't give the second tar any input directly, because it is reading its input from the pipe, not the keyboard or any regular file.

In the 3rd step it states f - designates the target file as stdout, but there is nothing in output right now, while creating archive, from where is the name of file supplied?

stdin and stdout are two data streams that are created by OS for every process (a command that is run). The process may or may not use these streams but OS will create them anyways.

This is where the first process is writing its output to.

In-memory data streams need not have a file name, these are not regular files on disk.

In the 8th step it states, it reads data from stdin, but I didn't give any input, is there any input left in the stream?

There are 2 processes separated by a pipe |and you can visualize it as:

(cd /source/directory && tar cf - . ) -> [stdout] -> | -> [stdin] -> (cd /dest/directory && tar xpvf -)

So, the first process on left hand side writes the output to its own stdout . The pipe | is OS level plumbing that pumps data from stdout of previous process to stdin of next process. The process on right hand side reads data from its stdin .

Also, like the pipe | pattern, the dash - is a common cli pattern to provide in place of a file, that tells the command to read write data to/from stdin/stdout instead of a file.

the first parenthesis does the following: it changes directory to /source/directory/ and generates a tar file whose content is the current directory "." and sends it to the standard output.

The second parenthesis changes directory to /dest/directory/ and extracts there the archive it reads from its standard input.

ie you tar the content of "/source/directory" and you untar it in "/dest/directory" without using an intermediate file to do so, just a pipe "|" to make the junction between the two commands.

NB: the parenthesis create a sub-process, so you've got a subprocess executing the tar c and another one executing the tar f running at the same time, the output of one sub-process being fed to the second sub-process.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM