BKoo
BKoo

Reputation: 115

Linux command ambiguous redirect

Hi I have a lab header called header.txt and I want to cat into my 3 C files cat ../header.txt > find -name *.c

What is wrong with the above statement?

Upvotes: 1

Views: 4017

Answers (3)

chepner
chepner

Reputation: 532518

Output redirection is for files, not commands. You'll need to process each file separately.

find -name *.c -print0 | while IFS= read -r -d '' f; do
  cat ../header.txt >> $f   # Append instead of overwriting
done

As for the 'ambiguous redirect', you normally get that when you write something like:

... > *.c

and the glob *.c expands to more than one file. For example:

$ echo "" >> *.c
-sh: *.c: ambiguous redirect
$

Upvotes: 0

Eevee
Eevee

Reputation: 48604

The I/O redirection operators <, >, etc. all only take one word as their argument, and use that as a filename. Anything else is considered part of the command line.

So when you run this:

cat ../header.txt > find -name *.c

It's exactly the same as this:

cat ../header.txt -name *.c > find

That's probably not going to do anything useful.

Another problem: your *.c isn't escaped or quoted, so bash will expand it rather than passing it to find.


You can do what you seem to want with tee, which accepts any number of arguments:

cat ../header.txt | tee *.c

And then you don't even need cat any more, really.

tee *.c < ../header.txt

Of course, you could just as well do this with cp. Perhaps you meant to append to these files? If so, pass -a to tee as well.


Interesting trivia: zsh and some other shells will let you have multiple > operators, which works just like tee. (Multiple < is also allowed and works like cat.)

cat infile > outfile1 > outfile2

But you have to actually list every file individually, so you can't use this shortcut with a glob like *.c.

Upvotes: 4

Jonathan Leffler
Jonathan Leffler

Reputation: 755094

You can prefix your C files with the lab's header using:

for file in *.c
do cat ../header.txt "$file" > x
   mv x "$file"
done

If this were going to be a production operation, you'd worry about using a unique file name as the temporary (I'm just assuming that if you're careless enough to have a file called x lying around, it doesn't contain anything important), and you would deal with interrupts etc and clean up the intermediate file. You can meditate on whether it is better to use mv or cp to replace the original file — contemplate permissions, symbolic links, hard links and cleanup once again.

Upvotes: 0

Related Questions