Just to be clear, those aren't "inputs", they're arguments (aka parameters). Input can be piped via < (input from file to the left side) or | (input from stream to the right side). There's a difference.
–
goldilocksJun 11 '14 at 14:46

6

Not an answer to your question, but maybe an answer to your problem: In bash, the yank-last-arg command (default shortcut Meta-. or Meta-_; Meta often being the left Alt key) will copy the last parameter from the preceding command line into the current one. So, after executing stat fileName you type file [Meta-.] and do not have to type that fileName again. I always use that.
–
DubuJun 12 '14 at 10:18

1

And the difference is that < and > are redirection, not piping. A pipeline connects two processes, while redirection simply reassigns stdin/stdout.
–
bdowningJun 12 '14 at 18:47

@bdowning: Yeah, but you're redirecting the pipe though aren't you. You can redirect the start of a pipeline to be reading from a file on disk, or you can redirect the end of a pipeline to be writing to a file on disk. Still piping. ;-)
–
James HaighJun 13 '14 at 15:43

{ stat -; file -;} < filename is magic. stat must be checking to see that its stdin is connected to a file and reporting the file's attributes? Presumably not advancing the pointer on stdin therefore allowing file to sniff stdin contents
–
1_CRJun 11 '14 at 16:22

stat - is handled specially since coreutils-8.0 (Oct 2009), in versions prior to that you will get an error (unless you have a file called - from a previous experiment, in which case you'll get the wrong results...)
–
mr.spuraticJun 12 '14 at 11:03

1

@mr.spuratic. Yes, and BSDs, IRIX and zsh stats won't recognise it either. With zsh and IRIX stat, you can use stat -f0 instead.
–
Stéphane ChazelasJun 12 '14 at 11:43

All of these answers seem like scripting to me, to a greater or lesser extent. For a solution that really involves no scripting, and assumes that you're sitting at the keyboard typing into a shell, you can try:

stat somefile Enter
file Esc_ Enter

In bash, zsh, and ksh at least, in both vi and emacs modes, pressing Escape and then underscore inserts the last word from the previous line into the edit buffer for the current line.

Or, you can use history substitution:

stat somefile Enter
file !$ Enter

In bash, zsh, csh, tcsh, and most other shells, !$ is replaced with the last word of the previous command line when the current command line is parsed.

@shadyabhi ^ Links for both bash and zsh's standard keybindings. Note that bash is just using readline, so (most of) the bash ones will work in any application that uses the readline library.
–
godlygeekJun 17 '14 at 17:20

The way I have found to do this reasonably simply is using xargs, it takes a file / pipe and converts its contents into a program arguments . This can be combined with tee which splits a stream and sends it to two or more programs, In your case you need:

echo filename | tee >(xargs stat) >(xargs file) | cat

Unlike many of the other answers this will work in bash and most other shells under Linux. I shall suggest this is a good use case of a variable but if you absolutely cannot use one this is the best way to do it only with pipes and simple utilities (assuming you do not have a particularly fancy shell).

Additionally you can do this for any number of programs by simply adding them in the same manner as these two after the tee.

EDIT

As suggested in the comments there are a couple of flaws in this answer, the first is the potential for output interlacing. This can be fixed as so:

echo filename | tee >(xargs stat) >(( wait $!; xargs file )) | cat

This will force the commands to run in turn and output will never be interlaced.

The second issue is avoiding process substitution which is not available in some shells, this can be achieved by using tpipe instead of tee as so:

echo filename | tpipe 'xargs stat' | ( wait $!; xargs file )

This should be portable to nearly any shell (I hope) and solves the issues in the other commend, however I am writing this last one from memory as my current system does not have tpipe available.

Process substitution is a ksh feature that only works in ksh (not the public domain variants), bash and zsh. Note that stat and file will run concurrently, so possibly their output will be intertwined (I suppose you're using | cat to force output buffering to limit that effect?).
–
Stéphane ChazelasJun 11 '14 at 17:40

@StéphaneChazelas You are correct about cat, when using it I have not managed to ever produce a case of interlaced input when using it. However I am going to try something to produce a more portable solution momentarily.
–
ValityJun 11 '14 at 20:52

I think you are asking a wrong question, at least for what you are trying to do.
stat and file commands are taking parameters which is the name of a file and not the content of it. It is later on the command which does reading of the file identified by the name you are specifying.

A pipe is supposed to have two ends, one used as input and another one as output and this make sense as you might need to do different processing along the way with different tools until you get needed result. Saying that you know how to pipe outputs but don't know how to pipe inputs is not correct in principle.

In your case you don't need a pipe at all since you have to provide the input in a form of a file name. And even if those tools (stat and file) would read stdin, pipe is not relevant here again as input should not be altered by any of the tool when it gets to the second one.

@StephaneChezales - all of that is fixed now except for the possibility of the hardquote. I could handile that with a single seds/// I guess, but its about of scope - and if people are putting that in their filenames they should be using windows.
–
mikeservJun 11 '14 at 21:21

@StéphaneChazelas - nevermind - I forgot how easy those were to handle.
–
mikeservJun 11 '14 at 21:27

Strictly speaking, this is not an answer to the question as asked: “How can you execute both commands on the same input (without typing the input … twice)?” (emphasis added). Your answer applies to all files in the current directory – and it includes * twice. You might as well say stat -- *; file -- *.
–
ScottJul 24 '14 at 20:17

@Scott - the input is not typed twice - * is expanded. The expansion of * plus the two commands for every argument in* is the input. See? printf commands\ %s\;shift *
–
mikeservJul 24 '14 at 20:27

There are a few different references to 'input' here, so I will give a few scenarios with understanding it in mind first. For your quick answer to the question in shortest form:

stat testfile < <($1)> outputfile

The above will perform a stat on testfile, take (redirect) it's STDOUT and include that into the next special function (the <() part) then output the final results of whatever that was, into a new file (outputfile). The file is called, then referenced with bash built-ins ($1 each time after, until you begin a new set of instructions).

Your question is great, and there are several answers and ways to do this, but it does indeed change with what you are doing specifically.

For instance, you can loop that as well, which is quite handy. A common usage of this is, in psuedo-code mindset, is:

run program < <($output_from_program)> my_own.log

Taking that in and expanding on that knowledge allows you to create things such as:

This will perform a simple ls -A on your current directory, then tell while to loop through each result from the ls -A to (and here's where it's tricky!) grep "thatword" in each of those results, and only perform the previous printf (in red) if it actually found a file with "thatword" in it. It will also log the results of the grep into a new text file, files_that_matched_thatword.

where QuickBrownFoxJumpsOverTheLazyDog is a placeholder,
necessary because "$@" is equivalent to "$1" "$2" "$3" …,
so you need to interpose something to be assigned to "$0", which is then never used.
The placeholder can be any single word, such as a null string ("") or a hyphen (-).

That $0 is the name you want to give to that inline script. It's used for instance in error messages by the shell for that script. Like when file or stat can't be found or can't be executed for any reason. So, you want something meaningful here. If not inspired, just use sh.
–
Stéphane ChazelasJun 20 at 18:13