{
    "mode": "info",
    "parameter": "tee",
    "section": "",
    "url": "https://www.chedong.com/phpMan.php/info/tee/json",
    "generated": "2026-11-11T09:38:55Z",
    "sections": {
        "File: coreutils.info,  Node: tee invocation,  Up: Redirection": {
            "content": "",
            "subsections": [
                {
                    "name": "17.1 'tee': Redirect output to multiple files or processes",
                    "content": ""
                }
            ]
        },
        "The 'tee' command copies standard input to standard output and also to": {
            "content": "any files given as arguments.  This is useful when you want not only to\nsend some data down a pipe, but also to save a copy.  Synopsis:\n\ntee [OPTION]... [FILE]...\n\nIf a file being written to does not already exist, it is created.  If\na file being written to already exists, the data it previously contained\nis overwritten unless the '-a' option is used.\n\nIn previous versions of GNU Coreutils (5.3.0-8.23), a FILE of '-'\ncaused 'tee' to send another copy of input to standard output.  However,\nas the interleaved output was not very useful, 'tee' now conforms to\nPOSIX and treats '-' as a file name.\n\nThe program accepts the following options.  Also see *note Common\noptions::.\n\n'-a'\n'--append'\nAppend standard input to the given files rather than overwriting\nthem.\n\n'-i'\n'--ignore-interrupts'\nIgnore interrupt signals.\n\n'-p'\n'--output-error[=MODE]'\nAdjust the behavior with errors on the outputs.  In summary '-p'\nallows 'tee' to operate in a more appropriate manner with pipes,\nand to continue to process data to any remaining outputs, if any\npipe outputs exit early.  The default operation when\n'--output-error' is not specified is to exit immediately on error\nwriting to a pipe, and diagnose errors writing to a non-pipe.  The\nlong form '--output-error' option supports selection between the\nfollowing MODEs:\n\n'warn'\nWarn on error opening or writing any output, including pipes.\nWriting is continued to still open files/pipes.  Exit status\nindicates failure if any output has an error.\n\n'warn-nopipe'\nThis is the default MODE when not specified, or when the short\nform '-p' is used.  Warn on error opening or writing any\noutput, except pipes.  Writing is continued to still open\nfiles/pipes.  Exit immediately if all remaining outputs become\nbroken pipes.  Exit status indicates failure if any non pipe\noutput had an error.\n\n'exit'\nExit on error opening or writing any output, including pipes.\n\n'exit-nopipe'\nExit on error opening or writing any output, except pipes.\nExit immediately if all remaining outputs become broken pipes.\n\nThe 'tee' command is useful when you happen to be transferring a\nlarge amount of data and also want to summarize that data without\nreading it a second time.  For example, when you are downloading a DVD\nimage, you often want to verify its signature or checksum right away.\nThe inefficient way to do it is simply:\n\nwget https://example.com/some.iso && sha1sum some.iso\n\nOne problem with the above is that it makes you wait for the download\nto complete before starting the time-consuming SHA1 computation.",
            "subsections": []
        },
        "Perhaps even more importantly, the above requires reading the DVD image": {
            "content": "a second time (the first was from the network).\n\nThe efficient way to do it is to interleave the download and SHA1\ncomputation.  Then, you'll get the checksum for free, because the entire\nprocess parallelizes so well:\n\n# slightly contrived, to demonstrate process substitution\nwget -O - https://example.com/dvd.iso \\\n| tee >(sha1sum > dvd.sha1) > dvd.iso\n\nThat makes 'tee' write not just to the expected output file, but also\nto a pipe running 'sha1sum' and saving the final checksum in a file\nnamed 'dvd.sha1'.\n\nNote, however, that this example relies on a feature of modern shells\ncalled \"process substitution\" (the '>(command)' syntax, above; *Note",
            "subsections": []
        },
        "Process Substitution: (bash)Process Substitution.), so it works with": {
            "content": "'zsh', 'bash', and 'ksh', but not with '/bin/sh'.  So if you write code\nlike this in a shell script, be sure to start the script with\n'#!/bin/bash'.\n\nNote also that if any of the process substitutions (or piped standard\noutput) might exit early without consuming all the data, the '-p' option\nis needed to allow 'tee' to continue to process the input to any\nremaining outputs.\n\nSince the above example writes to one file and one process, a more\nconventional and portable use of 'tee' is even better:\n\nwget -O - https://example.com/dvd.iso \\\n| tee dvd.iso | sha1sum > dvd.sha1\n\nYou can extend this example to make 'tee' write to two processes,\ncomputing MD5 and SHA1 checksums in parallel.  In this case, process\nsubstitution is required:\n\nwget -O - https://example.com/dvd.iso \\\n| tee >(sha1sum > dvd.sha1) \\\n>(md5sum > dvd.md5) \\\n> dvd.iso\n\nThis technique is also useful when you want to make a compressed\ncopy of the contents of a pipe.  Consider a tool to graphically\nsummarize file system usage data from 'du -ak'.  For a large hierarchy,\n'du -ak' can run for a long time, and can easily produce terabytes of\ndata, so you won't want to rerun the command unnecessarily.  Nor will\nyou want to save the uncompressed output.\n\nDoing it the inefficient way, you can't even start the GUI until\nafter you've compressed all of the 'du' output:\n\ndu -ak | gzip -9 > /tmp/du.gz\ngzip -d /tmp/du.gz | checkspace -a\n\nWith 'tee' and process substitution, you start the GUI right away and\neliminate the decompression completely:\n\ndu -ak | tee >(gzip -9 > /tmp/du.gz) | checkspace -a\n\nFinally, if you regularly create more than one type of compressed\ntarball at once, for example when 'make dist' creates both\n'gzip'-compressed and 'bzip2'-compressed tarballs, there may be a better\nway.  Typical 'automake'-generated 'Makefile' rules create the two\ncompressed tar archives with commands in sequence, like this (slightly\nsimplified):\n\ntardir=your-pkg-M.N\ntar chof - \"$tardir\" | gzip  -9 -c > your-pkg-M.N.tar.gz\ntar chof - \"$tardir\" | bzip2 -9 -c > your-pkg-M.N.tar.bz2\n\nHowever, if the hierarchy you are archiving and compressing is larger\nthan a couple megabytes, and especially if you are using a\nmulti-processor system with plenty of memory, then you can do much\nbetter by reading the directory contents only once and running the\ncompression programs in parallel:\n\ntardir=your-pkg-M.N\ntar chof - \"$tardir\" \\\n| tee >(gzip -9 -c > your-pkg-M.N.tar.gz) \\\n| bzip2 -9 -c > your-pkg-M.N.tar.bz2\n\nIf you want to further process the output from process substitutions,\nand those processes write atomically (i.e., write less than the system's\nPIPEBUF size at a time), that's possible with a construct like:\n\ntardir=your-pkg-M.N\ntar chof - \"$tardir\" \\\n| tee >(md5sum --tag) > >(sha256sum --tag) \\\n| sort | gpg --clearsign > your-pkg-M.N.tar.sig\n\nAn exit status of zero indicates success, and a nonzero value\nindicates failure.\n",
            "subsections": []
        }
    },
    "flags": [],
    "examples": [],
    "see_also": []
}