How does this work? input/output redirection, subshell

#!/bin/bash
#: Title       : scanvirus_test

control_c()
# run if user hits control-c
{
printf 'Exiting...
'
scanvirus_trap_flag='true'
}

#trap keyboard interrupt (control-c)
scanvirus_trap_flag='false'   
trap control_c 2

#read output of 'clamscan -r' info command_output var array
while read -ra command_output; do

     printf "%s %s %s %s %s
" ${command_output[0]} ${command_output[1]} ${command_output[2]} ${command_output[3]}  ${command_output[4]} 

     #if control-c pressed exit loop
     if  "$scanvirus_trap_flag" = 'true' ]; then
             break
     fi

done < <(clamscan -r /)

echo “Hello there…” > temp.txt redirect standard output to file.

done < <(clamscan -r)

This is redirecting standard output into the while loop. The while loop is taking it’s input from the output of the clamscan. The line should look like this.

done < (clamscan -r /)

This gives an error. How the ‘<<’ line work? I can’t understand why it works.

I think it needs to be “<<” rather than “< <”. You have an extra space there.

Check “man bash” for the redirection operators.

Like nrickert I wonder if you have studied man bash. Most of us are willing to help in understanding the documentation and in helping finding prgramming errors you made. But we assume that you did the most obvious things first yourself.

Redirection with < is NOT redirecting standard output as you state above. It is redirecting standard input.

The usage of << (not < < as you use) is about a “here document”. Look that up in the docs.

Standard input redirection is of the form:

command < file

which will see that when command reads from standard input, the input will be read fom file.
You have

.....
done < (clamscan -r /) 

which would mean that (clamscan -r /), after all the word splitting and expansion that bash does to an input line, should be the name of a file. I doubt it is.
(it is three words instead of one and even the first word (clamscan is probably not an existing file.

An assumption:
when you want to read in the loop the output of a command, that is done using a pipe:

clamscan -r | while read ........

It is redirecting standard output of command in parenthesis.

not < < as you use

That’s not was was used by OP. Please look in bash manual what <(…) means. :slight_smile:

I still fail to comprehend what was the question originally.

What do you mean with “it” here? When I understand what is below, the first < redirects to standard input.

I found tthis

Process Substitution

Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of <(list ) or >(list ). The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list ) form is used, writing to the file will provide input for list. If the <(list ) form is used, the file passed as an argument should be read to obtain the output of list.

When available, process substitution is performed simultaneously with parameter and variable expansion, command substitution, and arithmetic expansion.

Rather obscure (and typicaly bash?). This is thus executed at command line interpretion annd not on command line execution (is that whaht the OP wants?). And it depends on “systems that support …”. Very tricky IMHO.

And the explanation of the OP

which will see that when command reads from standard input, the input will be read fom file.
is very vague: which file?

I agree with you. The OPonly tells what he thinks he sees, but he never tell what his goals are.

My interpretation that he wants the output of the clamscan command piped to the while command is something of a guess.

I referred to original statement

echo “Hello there…” > temp.txt redirect standard output to file and done < <(clamscan -r) is redirecting standard output into the while loop

which is technically correct and by context second part refers to “clamscan -r” output.

Very tricky IMHO.

Well, it is useful if command requires explicit file for input/output, to avoid penalty (space and time) associated with creating of temporary files. I first saw it in zsh and I think bash implemented it later.

I am not sure, but is that done rather recently?

I studied the whole sequence of word splitting, all types of expansion, etc. not to long ago to create some documentation in the Dutch section here. I can not remember to have seen it then.

Most of us are willing to help in understanding the documentation and in helping finding prgramming errors you made. But we assume that you did the most obvious things first yourself.

This a copy of someone else’s code that was a solution to my problem. I didn’t understand how it worked. Also, I have two thick linux books for reference.

done < <(clamscan -r /)

Reading the comments, it should look like one of these.

done <<(clamscan -r /)

done << (clamscan -r /)

Back to my original question. Pipe ‘|’ is another coding issue. I’ll look at that later.

#redirect output to 'output.txt'
echo "hello there..." > output.txt

#redirect output to 'output.txt', append to the end of file
echo "hello there..." >> output.txt

#redirect input from subshell line output to while loop.
done < (clamscan -r /)

#redirect input append from subshell line output to while loop.
done << (clamscan -r /)

Input append isn’t listed in either linux book. Not counting spaces, the correct usage should be single ‘<’.

#redirect input from subshell line output to while loop.
done < (clamscan -r /)

Can someone explain the logic here?

No, it should not.

II thought I had already shown to you how to pipe the standard output of a program into the standard input of another, wher that “another” matbe a while loop?

clamscan -r / | while read .........
do     .........
        ..........
done

Back to my original question. Pipe ‘|’ is another coding issue. I’ll look at that later.

Piping input and output, I understand. This is about understanding redirection of input syntax, not blindly writing code down. I’v been reading all the comments and reading on input/output redirection. This line is presented in three different syntax formats.

While loop line read command input ← subshell: (clamscan - r /)

done < <(clamscan -r /)  #input append redirection, input redirection twice?  This coding works, why?
done <<(clamscan -r /)  #input append redirection?  input redirection twice?
done <(clamscan -r /)   #input redirection, doesn't work.  

Syntax: Why it’s ‘<’ input redirection or ‘<<’ input append redirection? I can use it, but not understanding it causes me problems in coding later. Also, I will test them again later. ??

arvidjaar> what’s the correct format? single or double ‘<’. Spacing? Syntax?

What part of bash manual you do not understand?

It’s not the same. Due to the way pipes are implemented in bash, the right part runs in subprocess so it is impossible to change variable in main shell from within “while” loop in this case. Got in this trap several times. Process redirection helps here.

A single re-direction symbol ( > or <) replaces.
A double re-direction symbol ( >> or <<) appends.

Spaces are usually suppressed but I suspect is not a constant and consistent syntax format in all consoles.

As for syntax, nowadays I recommend building a library of examples for what you want to do.
In the old days before the ability of today’s search engines, examples and explanation was insufficient so you had to learn by instruction but today at least for me, learning by example is usually clearer.

I’m also a bit uncomfortable with using the term “piping” when you mean re-direction – To me, that refers specifically to the function represented by “|” which is altogether different.

AFAIK all of the above can be found easily in numerous articles on the Web and can easily be discovered by testing.

TSU

Hi,
I’ts been quite a while since I have been in the forums. :slight_smile: but As already mentioned the <( ) is a process substitution. In short whatever is the command inside that process substitution anyone/anything can read from it. but you still need the additional < so you have the < <( ) . Just think of the <( ) as a file and in order to read from that file you need the <. The same goes to >( ) in order to write in that file you need the >. A good example of using >( ) is for a logging the whole output of your script in a log file

exec > >(tee -a log.txt) 2>&1

put that code on top of your script and all the output should go (append) in that log.txt
>(tee -a log.txt) is the file and in order to write to that file you need the >
the -a flag of tee means append.

I’m not sure what is input append in your question.