Linux pass stdout as file name for command line util?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7756609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 06:40:42  来源:igfitidea点击:

pass stdout as file name for command line util?

linuxbashfile-iostdoutpipe

提问by Jake

I'm working with a command line utility that requires passing the name of a file to write output to, e.g.

I'm working with a command line utility that requires passing the name of a file to write output to, e.g.

foo -o output.txt

The only thing it writes to stdoutis a message that indicates that it ran successfully. I'd like to be able to pipe everything that is written to output.txtto another command line utility. My motivation is that output.txt will end up being a 40 GB file that I don't need to keep, and I'd rather pipe the streams than work on massive files in a stepwise manner.

The only thing it writes to stdoutis a message that indicates that it ran successfully. I'd like to be able to pipe everything that is written to output.txtto another command line utility. My motivation is that output.txt will end up being a 40 GB file that I don't need to keep, and I'd rather pipe the streams than work on massive files in a stepwise manner.

Is there any way in this scenario to pipe the real output (i.e. output.txt) to another command? Can I somehow magically pass stdoutas the file argument?

Is there any way in this scenario to pipe the real output (i.e. output.txt) to another command? Can I somehow magically pass stdoutas the file argument?

采纳答案by aioobe

Solution 1: Using process substitution

Solution 1: Using process substitution

The most convenient way of doing this is by using process substitution. In bash the syntax looks as follows:

The most convenient way of doing this is by using process substitution. In bash the syntax looks as follows:

foo -o >(other_command)

(Note that this is a bashism. There's similar solutions for other shells, but bottom line is that it's not portable.)

(Note that this is a bashism. There's similar solutions for other shells, but bottom line is that it's not portable.)

Solution 2: Using named pipesexplicitly

Solution 2: Using named pipesexplicitly

You can do the above explicitly / manually as follows:

You can do the above explicitly / manually as follows:

  1. Create a named pipe using the mkfifocommand.

    mkfifo my_buf
    
  2. Launch your other command with that file as input

    other_command < my_buf
    
  3. Execute fooand let it write it's output to my_buf

    foo -o my_buf
    
  1. Create a named pipe using the mkfifocommand.

    mkfifo my_buf
    
  2. Launch your other command with that file as input

    other_command < my_buf
    
  3. Execute fooand let it write it's output to my_buf

    foo -o my_buf
    

Solution 3: Using /dev/stdout

Solution 3: Using /dev/stdout

You can also use the device file /dev/stdoutas follows

You can also use the device file /dev/stdoutas follows

foo -o /dev/stdout | other_command

回答by ktf

You could use the magic of UNIX and create a named pipe :)

You could use the magic of UNIX and create a named pipe :)

  1. Create the pipe

    $ mknod -p mypipe
    
  2. Start the process that reads from the pipe

    $ second-process < mypipe
    
  3. Start the process, that writes into the pipe

    $ foo -o mypipe
    
  1. Create the pipe

    $ mknod -p mypipe
    
  2. Start the process that reads from the pipe

    $ second-process < mypipe
    
  3. Start the process, that writes into the pipe

    $ foo -o mypipe
    

回答by frankc

Named pipes work fine, but you have a nicer, more direct syntax available via bash process substitution that has the added benefit of not using a permanent named pipe that must later be deleted (process substitution uses temporary named pipes behind the scenes):

Named pipes work fine, but you have a nicer, more direct syntax available via bash process substitution that has the added benefit of not using a permanent named pipe that must later be deleted (process substitution uses temporary named pipes behind the scenes):

foo -o >(other command)

foo -o >(other command)

Also, should you want to pipe the output to your command and also save the output to a file, you can do this:

Also, should you want to pipe the output to your command and also save the output to a file, you can do this:

foo -o >(tee output.txt) | other command

foo -o >(tee output.txt) | other command

回答by Jaime Garza

I use /dev/tty as the output filename, equivalent to using /dev/nul/ when you want to output nothing at all. Then | and you are done.

I use /dev/tty as the output filename, equivalent to using /dev/nul/ when you want to output nothing at all. Then | and you are done.

回答by Nestor Urquiza

For the sake of making stackoverflow happy let me write a long enough sentence because my proposed solution is only 18 characters long instead of the required 30+

For the sake of making stackoverflow happy let me write a long enough sentence because my proposed solution is only 18 characters long instead of the required 30+

foo -o /dev/stdout