0

I would like to run a command for each entry in a column of a file. I am currently doing the following, but am getting an ambiguous redirect error.

while read -r entry;
do
  cmd "$entry" ;
done < $(cut -f2 file.tsv)

I've also tried

done <(cut -f2 file.tsv)

which throws an unexpected token syntax error.

What is the correct syntax for doing this?


Example Input

A tab separated values file with file paths in the column of interest.

1    file1.txt    ...
2    file2.txt    ...
3    file3.txt    ...

Expected Result

The script should run the commands

cmd file1.txt
cmd file2.txt
cmd file3.txt

For the purpose of a simple example, you can use cat as the cmd, since the error is not with the cmd per se, but with the input redirection.

The actual command I am running is the bioinformatics tool kallisto, specifically kallisto quant.

closed as off-topic by Stephen Harris, Vlastimil, user88036, Thomas, RalfFriedl Sep 23 '18 at 12:32

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions describing a problem that can't be reproduced and seemingly went away on its own (or went away when a typo was fixed) are off-topic as they are unlikely to help future readers." – Stephen Harris, Vlastimil, Community, Thomas
If this question can be reworded to fit the rules in the help center, please edit the question.

  • Please state the actual command in your question. – Vlastimil Sep 23 '18 at 2:35
0

Looks like this is the right way to do it:

while read -r entry;
do
  cmd "$entry" ;
done < <(cut -f2 file.tsv)

According to this bash redirection cheat sheet, this syntax passes the output of cut -f2 file.tsv to an anonymous fifo, then passes that to stdin.

  • Would really appreciate to know why this is getting downvoted. Personally, I find this more readable than Goro's answer. – merv Sep 23 '18 at 3:11
0

Your code can be revised as follows:

cut -f2  file.tsv | while read -a entry;
do
  cmd "$entry" ;

done

Please note, whenever you run a shell script, it creates a new process called subshell and your script will get executed using a subshell. However, a Subshell can be used to do parallel processing. If you start another shell on top of your current shell, it can be referred to as a subshell. Type the following command to see subshell value:

echo $BASH_SUBSHELL

OR

echo "Current shell: $BASH_SUBSHELL"; ( echo "Running du in subshell: $BASH_SUBSHELL" ;cd /tmp; du 2>/tmp/error 1>/tmp/output)

Any commands enclosed within parentheses are run in a subshell.

  • 1
    Note that in bash, the cmd is run in a subshell and so any variables and related values won't be set. The original command (if done correctly) is run in the current shell. – Stephen Harris Sep 23 '18 at 3:00
  • @StephenHarris, just making sure I follow: You're saying input redirection doesn't trigger a subshell, but piping does? – merv Sep 23 '18 at 3:41
  • 1
    Using a pipe causes the while loop (and so cmd) to be run in a subshell. Using redirection means that the while loop is run in the parent process. – Stephen Harris Sep 23 '18 at 11:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.