Linux command ambiguous redirect

后端 未结 3 962
再見小時候
再見小時候 2021-01-26 09:58

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?

相关标签:
3条回答
  • 2021-01-26 10:25

    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.

    0 讨论(0)
  • 2021-01-26 10:25

    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
    $
    
    0 讨论(0)
  • 2021-01-26 10:40

    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.

    0 讨论(0)
提交回复
热议问题