Shell Duplicating stdin

I'm trying to work on a script but I keep losing stdin data after calling the file cat foo | test.sh:

Code:
#!/usr/local/bin/bash

filetype = `/usr/bin/file -b -`

cat > /tmp/fee

/tmp/fee will be empty.

I have tried using exec and setting a variable to stdin at the beginning.

My bash skills are not the best, so I am hoping someone has an idea about what I am doing wrong.

Thanks,

Bill
 
For starters, don't script in bash, just use sh.

Second, can you clarify exactly what it is you're trying to do?
 
I need to read stdin and run file to determine the file type. But then I need to send the original stdin to stdout

Bill
 
I am not sure what you want to do. It might be that tee is the command you are looking for. Please have a look at the short man page of tee. stdin is sent to stdout and to an additional file. Afterwards you can use file to retrieve the information about the file.
 
I am not sure what you want to do. It might be that tee is the command you are looking for. Please have a look at the short man page of tee. stdin is send to stdout and to an additional file. Afterwards you can use file to retrieve the information about the file.

If you look at the small script in post 1, I want the output of the file command saved in variable filetype (this part works fine). But I also want file foo to be sent to /tmp/fee. If I # out the filetype line then /tmp/fee would look just like foo.

Hopefully this makes more sense.

Bill

p.s. I tried tee, to no avail. But maybe someone better than I can make it work.
 
Should /tmp/fee look like foo? if yes cat foo | tee /tmp/fee | test.sh might do the job. Or do you want /tmp/fee as a copy of foo with the output of file on top? Maybe an example can clarify this.
 
Rather than messing with tee(), just save stdin to a temporary file in /tmp. Use $$ to generate a filename. Then run file(1) on the temporary file, and use the temporary file for input to whatever conversion program is needed.
 
Rather than messing with tee(), just save stdin to a temporary file in /tmp. Use $$ to generate a filename. Then run file(1) on the temporary file, and use the temporary file for input to whatever conversion program is needed.

I thought abut this, but I want to avoid writing out the file if possible. My main fear was if it was a large file there would be a time delay.

Bill
 
The minute amount of time to create a temporary file will be hidden by the time spent in processing and transferring it to the printer.
 
I say that from having run several print servers which processed files continuously, some of them up to hundreds of megabytes in size.
 
And now to get to the answer (I love shell scripting, in my opinion it's way under appreciated): variables.

Now, this isn't a perfect solution because it also strips away the CR/LF characters, so everything ends up on one line. Still; that should be solvable by reading individual lines from /dev/stdin (I don't have time to check right now).

So something like this:

Code:
#!/bin/sh

file=`cat /dev/stdin`;
filetype=`echo $file | file -b -`;
echo $filetype
echo $file
 
For starters, don't script in bash, just use sh.

Okay, this is slightly off-topic, but this is not really very good advice.

Bash has many additions to sh, some (like [[) provide minor benefits, others (like set -o pipefail) are quite significant and impossible to do in a POSIX shell.

All this comes with some drawbacks, your performance will be less, and Bash is slightly less portable than a POSIX shell, but the advantages are significant. Performance often isn't that much of an issue, and Bash is still quite portable.

We BSD folk sometimes complain about "Linuxisms", one of them is using Bash, and it's true that scripts setting the hashbang to /bin/bash is annoying, especially when the script is just a POSIX shell (and not bash), but I think that "never use Bash, always use /bin/sh" is just as much of a BSDism as "always use bash" can be called a Linuxism.
 
If you need the features of bash, or find yourself working around the many extreme limitations of /bin/sh, it's an indicator that a more powerful programming language is needed.
 
If you need the features of bash, or find yourself working around the many extreme limitations of /bin/sh, it's an indicator that a more powerful programming language is needed.

I disagree, first of all, shell scripting is very powerful, which is exactly why it's still in use in spite of its shortcomings. Bash reduces some of those shortcomings, why not use it? The drawbacks are usually small, and the advantages (can be) quite large.

(That being said, while powerful, neither the POSIX shell nor Bash scale very well, and using a "real" programming language should generally be considered before embarking on a shell script.)
 
(that being said, while powerful, neither the POSIX shell nor bash scale very well, and using a "real" programming language should generally be considered before embarking on a shell script)

Exactly. sh can do things, it's just so lacking in expressiveness and power that the code is far more difficult to write, debug, and maintain.
 
And now to get to the answer (I love shell scripting, in my opinion it's way under appreciated): variables.

Now, this isn't a perfect solution because it also strips away the CR/LF characters, so everything ends up on one line. Still; that should be solvable by reading individual lines from /dev/stdin (I don't have time to check right now).

So something like this:

Code:
#!/bin/sh

file=`cat /dev/stdin`;
filetype=`echo $file | file -b -`;
echo $filetype
echo $file

Mine ended looking pretty simple. Again, I'm not a shell scripting wizard so there may be obvious mistakes.

Code:
#!/bin/sh

tmpfile=/tmp/bill.$$
cat > $tmpfile

filetype=`/usr/bin/file -b /tmp/bill.$$`
trimmed=`expr "$filetype" : '\(...\)'`

case "$trimmed" in
PDF)
    cat $tmpfile | \
    /usr/local/bin/pdf2ps - - && printf "\004" && exit 0
    rm $tmpfile
    exit 2
    ;;

Pos)
    cat $tmpfile &&  printf "\004" && exit 0
    rm $tmpfile
    exit 2
    ;;
 
The tempfile will not be removed with that code, the script ends after exit 0.

There is no need to use expr() on the return from file(), just match a string followed by a star:
Code:
case "filetype" in
PDF*)
  ...
PostScript*)
  ...
 
From mktemp(1):
The mktemp utility is provided to allow shell scripts to safely use tem-
porary files. Traditionally, many shell scripts take the name of the
program with the pid as a suffix and use that as a temporary file name.
This kind of naming scheme is predictable and the race condition it cre-
ates is easy for an attacker to win. A safer, though still inferior,
approach is to make a temporary directory using the same naming scheme.
While this does allow one to guarantee that a temporary file will not be
subverted, it still allows a simple denial of service attack. For these
reasons it is suggested that mktemp be used instead.
 
Back
Top