exec command in bash loop for webscrappingWhat does exec 3<&1 do?How does exec bash builtin work internally?for loop in bashFile descriptors across execUse case / practical example for Bash' builtin execreason for exec in wrapper scriptsPipe inside exec command won't workBash Script exec file descriptor returning “not found”What does `exec “$@”` do?bash - use exec for file descriptors using environment variables

My large rocket is still flipping over

Convert Numbers To Emoji Math

How long does it take a postcard to get from USA to Germany?

What does the phrase "go for the pin" mean here?

Why increasing of the temperature of the objects like wood, paper etc. doesn't fire them?

Why are condenser mics so much more expensive than dynamics?

How to say something covers all the view up to the horizon line?

Emergency stop in plain TeX, pdfTeX, XeTeX and LuaTeX?

Reverse ColorFunction or ColorData

Is there a reason why Turkey took the Balkan territories of the Ottoman Empire, instead of Greece or another of the Balkan states?

Hostile Divisor Numbers

Debian 9 server no sshd in auth.log

Is there any other simpler way to draw the following cross section?

All of my Firefox add-ons been disabled suddenly, how can I re-enable them?

Is it normal for gliders not to have attitude indicators?

Subnumcases as a part of align

How long did it take Captain Marvel to travel to Earth?

HSA - Continue to Invest?

Can a player choose to add detail and flavor to their character's spells and abilities?

Who filmed the Apollo 11 trans-lunar injection?

What do you call a painting painted on a wall?

Old story about a creature laying pyramid shaped eggs on Mars

Referring to person by surname, keep or omit "von"?

What does のそ mean on this picture?



exec command in bash loop for webscrapping


What does exec 3<&1 do?How does exec bash builtin work internally?for loop in bashFile descriptors across execUse case / practical example for Bash' builtin execreason for exec in wrapper scriptsPipe inside exec command won't workBash Script exec file descriptor returning “not found”What does `exec “$@”` do?bash - use exec for file descriptors using environment variables






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








1















Here is a simple script which is curling https://unix.stackexchange.com/ and storing the result into an array, which is working fine.



#!/usr/local/bin/bash
[ -f pgtoscrap ] && rm pgtoscrap; ;
curl -o pgtoscrap https://unix.stackexchange.com/;
declare -a arr;
fileName="pgtoscrap";

exec 10<&0
exec < $fileName
let count=0
while read LINE; do
arr[$count]=$LINE
((count++))
done
exec 0<10 10<&-


But, each time I run this script; I get some error for the wrong file descriptor.



./shcrap
./shcrap: line 14: 10: No such file or directory


I think I don't understand well how to use exec command in a loop correctly. Can someone explain?



-- Update after implementing mapfile for Bash 4 it became much simpler --



#!/usr/local/bin/bash
## Pass a parameter as e.g. ./linkscrapping.bash https://unix.stackexchange.com/
mapfile -t arr < <(curl -s $1); ## Doing exec stuff with process substitution
regex="<a[[:print:]]*</a>"; ELEMENTS=$#arr[@]; firstline=0;
for((i=0;i<$ELEMENTS;i++)); do
if [[ $arr[$i] =~ $regex ]]; then
[[ $firstline<1 ]] &&
echo $BASH_REMATCH[0] > scrapped; let firstline=$firstline+1; ||
echo $BASH_REMATCH[0] >> scrapped;
fi
done
pg2scrap="scrapped"; mapfile -t arr2 < <(cat $pg2scrap);
regex="href=["'][0-9a-zA-Z:/.]+"; ELEMENTS2=$#arr2[@]; line2=0
for ((i=0;i<$ELEMENTS2;i++)); do
if [[ $arr2[$i] =~ $regex ]]; then
[[ $line2<1 ]] &&
echo $BASH_REMATCH[0]#href=" > links; (( line2++ )); ||
echo $BASH_REMATCH[0]#href=" >> links;
fi
done; cat links;









share|improve this question



















  • 1





    Just for the record, you don't need that last exec at the end at all, unless you are sourcing the script or reusing this code in a function, because the file descriptor redirections don't effect the calling process from which the file descriptors are inherited, and because the file descriptors will be automatically closed when the shell process exits.

    – mtraceur
    yesterday

















1















Here is a simple script which is curling https://unix.stackexchange.com/ and storing the result into an array, which is working fine.



#!/usr/local/bin/bash
[ -f pgtoscrap ] && rm pgtoscrap; ;
curl -o pgtoscrap https://unix.stackexchange.com/;
declare -a arr;
fileName="pgtoscrap";

exec 10<&0
exec < $fileName
let count=0
while read LINE; do
arr[$count]=$LINE
((count++))
done
exec 0<10 10<&-


But, each time I run this script; I get some error for the wrong file descriptor.



./shcrap
./shcrap: line 14: 10: No such file or directory


I think I don't understand well how to use exec command in a loop correctly. Can someone explain?



-- Update after implementing mapfile for Bash 4 it became much simpler --



#!/usr/local/bin/bash
## Pass a parameter as e.g. ./linkscrapping.bash https://unix.stackexchange.com/
mapfile -t arr < <(curl -s $1); ## Doing exec stuff with process substitution
regex="<a[[:print:]]*</a>"; ELEMENTS=$#arr[@]; firstline=0;
for((i=0;i<$ELEMENTS;i++)); do
if [[ $arr[$i] =~ $regex ]]; then
[[ $firstline<1 ]] &&
echo $BASH_REMATCH[0] > scrapped; let firstline=$firstline+1; ||
echo $BASH_REMATCH[0] >> scrapped;
fi
done
pg2scrap="scrapped"; mapfile -t arr2 < <(cat $pg2scrap);
regex="href=["'][0-9a-zA-Z:/.]+"; ELEMENTS2=$#arr2[@]; line2=0
for ((i=0;i<$ELEMENTS2;i++)); do
if [[ $arr2[$i] =~ $regex ]]; then
[[ $line2<1 ]] &&
echo $BASH_REMATCH[0]#href=" > links; (( line2++ )); ||
echo $BASH_REMATCH[0]#href=" >> links;
fi
done; cat links;









share|improve this question



















  • 1





    Just for the record, you don't need that last exec at the end at all, unless you are sourcing the script or reusing this code in a function, because the file descriptor redirections don't effect the calling process from which the file descriptors are inherited, and because the file descriptors will be automatically closed when the shell process exits.

    – mtraceur
    yesterday













1












1








1








Here is a simple script which is curling https://unix.stackexchange.com/ and storing the result into an array, which is working fine.



#!/usr/local/bin/bash
[ -f pgtoscrap ] && rm pgtoscrap; ;
curl -o pgtoscrap https://unix.stackexchange.com/;
declare -a arr;
fileName="pgtoscrap";

exec 10<&0
exec < $fileName
let count=0
while read LINE; do
arr[$count]=$LINE
((count++))
done
exec 0<10 10<&-


But, each time I run this script; I get some error for the wrong file descriptor.



./shcrap
./shcrap: line 14: 10: No such file or directory


I think I don't understand well how to use exec command in a loop correctly. Can someone explain?



-- Update after implementing mapfile for Bash 4 it became much simpler --



#!/usr/local/bin/bash
## Pass a parameter as e.g. ./linkscrapping.bash https://unix.stackexchange.com/
mapfile -t arr < <(curl -s $1); ## Doing exec stuff with process substitution
regex="<a[[:print:]]*</a>"; ELEMENTS=$#arr[@]; firstline=0;
for((i=0;i<$ELEMENTS;i++)); do
if [[ $arr[$i] =~ $regex ]]; then
[[ $firstline<1 ]] &&
echo $BASH_REMATCH[0] > scrapped; let firstline=$firstline+1; ||
echo $BASH_REMATCH[0] >> scrapped;
fi
done
pg2scrap="scrapped"; mapfile -t arr2 < <(cat $pg2scrap);
regex="href=["'][0-9a-zA-Z:/.]+"; ELEMENTS2=$#arr2[@]; line2=0
for ((i=0;i<$ELEMENTS2;i++)); do
if [[ $arr2[$i] =~ $regex ]]; then
[[ $line2<1 ]] &&
echo $BASH_REMATCH[0]#href=" > links; (( line2++ )); ||
echo $BASH_REMATCH[0]#href=" >> links;
fi
done; cat links;









share|improve this question
















Here is a simple script which is curling https://unix.stackexchange.com/ and storing the result into an array, which is working fine.



#!/usr/local/bin/bash
[ -f pgtoscrap ] && rm pgtoscrap; ;
curl -o pgtoscrap https://unix.stackexchange.com/;
declare -a arr;
fileName="pgtoscrap";

exec 10<&0
exec < $fileName
let count=0
while read LINE; do
arr[$count]=$LINE
((count++))
done
exec 0<10 10<&-


But, each time I run this script; I get some error for the wrong file descriptor.



./shcrap
./shcrap: line 14: 10: No such file or directory


I think I don't understand well how to use exec command in a loop correctly. Can someone explain?



-- Update after implementing mapfile for Bash 4 it became much simpler --



#!/usr/local/bin/bash
## Pass a parameter as e.g. ./linkscrapping.bash https://unix.stackexchange.com/
mapfile -t arr < <(curl -s $1); ## Doing exec stuff with process substitution
regex="<a[[:print:]]*</a>"; ELEMENTS=$#arr[@]; firstline=0;
for((i=0;i<$ELEMENTS;i++)); do
if [[ $arr[$i] =~ $regex ]]; then
[[ $firstline<1 ]] &&
echo $BASH_REMATCH[0] > scrapped; let firstline=$firstline+1; ||
echo $BASH_REMATCH[0] >> scrapped;
fi
done
pg2scrap="scrapped"; mapfile -t arr2 < <(cat $pg2scrap);
regex="href=["'][0-9a-zA-Z:/.]+"; ELEMENTS2=$#arr2[@]; line2=0
for ((i=0;i<$ELEMENTS2;i++)); do
if [[ $arr2[$i] =~ $regex ]]; then
[[ $line2<1 ]] &&
echo $BASH_REMATCH[0]#href=" > links; (( line2++ )); ||
echo $BASH_REMATCH[0]#href=" >> links;
fi
done; cat links;






bash shell-script regular-expression file-descriptors exec






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday







Rakib Fiha

















asked May 2 at 13:59









Rakib FihaRakib Fiha

4110




4110







  • 1





    Just for the record, you don't need that last exec at the end at all, unless you are sourcing the script or reusing this code in a function, because the file descriptor redirections don't effect the calling process from which the file descriptors are inherited, and because the file descriptors will be automatically closed when the shell process exits.

    – mtraceur
    yesterday












  • 1





    Just for the record, you don't need that last exec at the end at all, unless you are sourcing the script or reusing this code in a function, because the file descriptor redirections don't effect the calling process from which the file descriptors are inherited, and because the file descriptors will be automatically closed when the shell process exits.

    – mtraceur
    yesterday







1




1





Just for the record, you don't need that last exec at the end at all, unless you are sourcing the script or reusing this code in a function, because the file descriptor redirections don't effect the calling process from which the file descriptors are inherited, and because the file descriptors will be automatically closed when the shell process exits.

– mtraceur
yesterday





Just for the record, you don't need that last exec at the end at all, unless you are sourcing the script or reusing this code in a function, because the file descriptor redirections don't effect the calling process from which the file descriptors are inherited, and because the file descriptors will be automatically closed when the shell process exits.

– mtraceur
yesterday










2 Answers
2






active

oldest

votes


















6














It surely has to do with how you close the file descriptor that you had opened earlier for stdin. Using the below should just be fine



exec 10<&- 


When you do 0<10, you instruct the shell to look for and to slurp in the contents of a file named 10 in your current directory which makes no sense in this context.



In bash you can also use an alternate form exec 10>&- which achieves the same purpose of closing the descriptor.



But that said, you don't need to use exec on random file descriptor and read your input, you can just read in your input with the process substitution technique in bash of form < <() as



while IFS= read -r line; do
arr["$count"]="$line"
((count++))
done< <(pgtoscrap)





share|improve this answer




















  • 2





    In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

    – BlackJack
    May 2 at 16:15






  • 1





    OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

    – mtraceur
    yesterday



















4














exec 10<&0 clones file descriptor number 0 to number 10, effectively saving the original so you can replace the file on fd 0 on the next line. To undo that, you'd need to reverse the numbers, to clone number 10 to number 0, exec 0<&10 (and then close fd 10 with exec 10<&-).



On the other hand, exec 0<10 without the ampersand is just a redirection with a filename 10. Since you don't have such a file, you get an error.




That said, you don't need to use exec to temporarily set up a redirection for the while loop. Compound commands can take redirections too, like so:



while read LINE; do
...
done < "$filename"


If you want to read full lines as they are, without whitespace or backslashes affecting the data, you need to unset IFS for read, and use read -r. Also, if you're appending to an array, you don't need to manually keep up with the indexes, you can just use += to append to the array directly:



arr=() # declares it an array and clears it, not strictly necessary though
while IFS= read -r line; do
arr+=("$line")
done < "$filename"


Or use mapfile (readarray) instead of a manual loop like @BlackJack mentions in comments:



mapfile -t arr < "$filename"


Or even without a temporary file at all:



#/bin/bash
mapfile -t arr < <(curl -s https://unix.stackexchange.com/)


(Without -t, mapfile leaves the line terminators in place.)






share|improve this answer























  • Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

    – Rakib Fiha
    yesterday












  • @RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

    – ilkkachu
    yesterday











Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f516774%2fexec-command-in-bash-loop-for-webscrapping%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









6














It surely has to do with how you close the file descriptor that you had opened earlier for stdin. Using the below should just be fine



exec 10<&- 


When you do 0<10, you instruct the shell to look for and to slurp in the contents of a file named 10 in your current directory which makes no sense in this context.



In bash you can also use an alternate form exec 10>&- which achieves the same purpose of closing the descriptor.



But that said, you don't need to use exec on random file descriptor and read your input, you can just read in your input with the process substitution technique in bash of form < <() as



while IFS= read -r line; do
arr["$count"]="$line"
((count++))
done< <(pgtoscrap)





share|improve this answer




















  • 2





    In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

    – BlackJack
    May 2 at 16:15






  • 1





    OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

    – mtraceur
    yesterday
















6














It surely has to do with how you close the file descriptor that you had opened earlier for stdin. Using the below should just be fine



exec 10<&- 


When you do 0<10, you instruct the shell to look for and to slurp in the contents of a file named 10 in your current directory which makes no sense in this context.



In bash you can also use an alternate form exec 10>&- which achieves the same purpose of closing the descriptor.



But that said, you don't need to use exec on random file descriptor and read your input, you can just read in your input with the process substitution technique in bash of form < <() as



while IFS= read -r line; do
arr["$count"]="$line"
((count++))
done< <(pgtoscrap)





share|improve this answer




















  • 2





    In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

    – BlackJack
    May 2 at 16:15






  • 1





    OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

    – mtraceur
    yesterday














6












6








6







It surely has to do with how you close the file descriptor that you had opened earlier for stdin. Using the below should just be fine



exec 10<&- 


When you do 0<10, you instruct the shell to look for and to slurp in the contents of a file named 10 in your current directory which makes no sense in this context.



In bash you can also use an alternate form exec 10>&- which achieves the same purpose of closing the descriptor.



But that said, you don't need to use exec on random file descriptor and read your input, you can just read in your input with the process substitution technique in bash of form < <() as



while IFS= read -r line; do
arr["$count"]="$line"
((count++))
done< <(pgtoscrap)





share|improve this answer















It surely has to do with how you close the file descriptor that you had opened earlier for stdin. Using the below should just be fine



exec 10<&- 


When you do 0<10, you instruct the shell to look for and to slurp in the contents of a file named 10 in your current directory which makes no sense in this context.



In bash you can also use an alternate form exec 10>&- which achieves the same purpose of closing the descriptor.



But that said, you don't need to use exec on random file descriptor and read your input, you can just read in your input with the process substitution technique in bash of form < <() as



while IFS= read -r line; do
arr["$count"]="$line"
((count++))
done< <(pgtoscrap)






share|improve this answer














share|improve this answer



share|improve this answer








edited May 2 at 14:41

























answered May 2 at 14:30









InianInian

5,5901632




5,5901632







  • 2





    In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

    – BlackJack
    May 2 at 16:15






  • 1





    OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

    – mtraceur
    yesterday













  • 2





    In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

    – BlackJack
    May 2 at 16:15






  • 1





    OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

    – mtraceur
    yesterday








2




2





In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

– BlackJack
May 2 at 16:15





In Bash 4 you could also use readarray arr < pgtoscrap instead of writing a loop. Or even curl -s https://unix.stackexchange.com/ | readarray arr to directly read the curl output into an array.

– BlackJack
May 2 at 16:15




1




1





OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

– mtraceur
yesterday






OP presumably intended to restore FD 0 by writing exec 0<&10 10<&-, and accidentally omitted the & ending up with 0<10.

– mtraceur
yesterday














4














exec 10<&0 clones file descriptor number 0 to number 10, effectively saving the original so you can replace the file on fd 0 on the next line. To undo that, you'd need to reverse the numbers, to clone number 10 to number 0, exec 0<&10 (and then close fd 10 with exec 10<&-).



On the other hand, exec 0<10 without the ampersand is just a redirection with a filename 10. Since you don't have such a file, you get an error.




That said, you don't need to use exec to temporarily set up a redirection for the while loop. Compound commands can take redirections too, like so:



while read LINE; do
...
done < "$filename"


If you want to read full lines as they are, without whitespace or backslashes affecting the data, you need to unset IFS for read, and use read -r. Also, if you're appending to an array, you don't need to manually keep up with the indexes, you can just use += to append to the array directly:



arr=() # declares it an array and clears it, not strictly necessary though
while IFS= read -r line; do
arr+=("$line")
done < "$filename"


Or use mapfile (readarray) instead of a manual loop like @BlackJack mentions in comments:



mapfile -t arr < "$filename"


Or even without a temporary file at all:



#/bin/bash
mapfile -t arr < <(curl -s https://unix.stackexchange.com/)


(Without -t, mapfile leaves the line terminators in place.)






share|improve this answer























  • Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

    – Rakib Fiha
    yesterday












  • @RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

    – ilkkachu
    yesterday















4














exec 10<&0 clones file descriptor number 0 to number 10, effectively saving the original so you can replace the file on fd 0 on the next line. To undo that, you'd need to reverse the numbers, to clone number 10 to number 0, exec 0<&10 (and then close fd 10 with exec 10<&-).



On the other hand, exec 0<10 without the ampersand is just a redirection with a filename 10. Since you don't have such a file, you get an error.




That said, you don't need to use exec to temporarily set up a redirection for the while loop. Compound commands can take redirections too, like so:



while read LINE; do
...
done < "$filename"


If you want to read full lines as they are, without whitespace or backslashes affecting the data, you need to unset IFS for read, and use read -r. Also, if you're appending to an array, you don't need to manually keep up with the indexes, you can just use += to append to the array directly:



arr=() # declares it an array and clears it, not strictly necessary though
while IFS= read -r line; do
arr+=("$line")
done < "$filename"


Or use mapfile (readarray) instead of a manual loop like @BlackJack mentions in comments:



mapfile -t arr < "$filename"


Or even without a temporary file at all:



#/bin/bash
mapfile -t arr < <(curl -s https://unix.stackexchange.com/)


(Without -t, mapfile leaves the line terminators in place.)






share|improve this answer























  • Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

    – Rakib Fiha
    yesterday












  • @RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

    – ilkkachu
    yesterday













4












4








4







exec 10<&0 clones file descriptor number 0 to number 10, effectively saving the original so you can replace the file on fd 0 on the next line. To undo that, you'd need to reverse the numbers, to clone number 10 to number 0, exec 0<&10 (and then close fd 10 with exec 10<&-).



On the other hand, exec 0<10 without the ampersand is just a redirection with a filename 10. Since you don't have such a file, you get an error.




That said, you don't need to use exec to temporarily set up a redirection for the while loop. Compound commands can take redirections too, like so:



while read LINE; do
...
done < "$filename"


If you want to read full lines as they are, without whitespace or backslashes affecting the data, you need to unset IFS for read, and use read -r. Also, if you're appending to an array, you don't need to manually keep up with the indexes, you can just use += to append to the array directly:



arr=() # declares it an array and clears it, not strictly necessary though
while IFS= read -r line; do
arr+=("$line")
done < "$filename"


Or use mapfile (readarray) instead of a manual loop like @BlackJack mentions in comments:



mapfile -t arr < "$filename"


Or even without a temporary file at all:



#/bin/bash
mapfile -t arr < <(curl -s https://unix.stackexchange.com/)


(Without -t, mapfile leaves the line terminators in place.)






share|improve this answer













exec 10<&0 clones file descriptor number 0 to number 10, effectively saving the original so you can replace the file on fd 0 on the next line. To undo that, you'd need to reverse the numbers, to clone number 10 to number 0, exec 0<&10 (and then close fd 10 with exec 10<&-).



On the other hand, exec 0<10 without the ampersand is just a redirection with a filename 10. Since you don't have such a file, you get an error.




That said, you don't need to use exec to temporarily set up a redirection for the while loop. Compound commands can take redirections too, like so:



while read LINE; do
...
done < "$filename"


If you want to read full lines as they are, without whitespace or backslashes affecting the data, you need to unset IFS for read, and use read -r. Also, if you're appending to an array, you don't need to manually keep up with the indexes, you can just use += to append to the array directly:



arr=() # declares it an array and clears it, not strictly necessary though
while IFS= read -r line; do
arr+=("$line")
done < "$filename"


Or use mapfile (readarray) instead of a manual loop like @BlackJack mentions in comments:



mapfile -t arr < "$filename"


Or even without a temporary file at all:



#/bin/bash
mapfile -t arr < <(curl -s https://unix.stackexchange.com/)


(Without -t, mapfile leaves the line terminators in place.)







share|improve this answer












share|improve this answer



share|improve this answer










answered May 2 at 16:37









ilkkachuilkkachu

63.7k10104183




63.7k10104183












  • Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

    – Rakib Fiha
    yesterday












  • @RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

    – ilkkachu
    yesterday

















  • Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

    – Rakib Fiha
    yesterday












  • @RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

    – ilkkachu
    yesterday
















Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

– Rakib Fiha
yesterday






Now, I understand the FD, so it's almost the same as a closing case, if statement esac, fi so on and so forth. I was foolishly thinking for 10<&0 it should be 0&<01. I think it might be better to use single digit FD to avoid confusion? so 9<&0 will end with 0&<9 9<&- Overall, using mapfile -t arr is far better approach I guess for Bash 4.

– Rakib Fiha
yesterday














@RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

– ilkkachu
yesterday





@RakibFiha, no, it'd still be 0<&9 9<&-. It's just the numbers that get switched, not the other characters. The action that happens is the same regardless of which number is cloned to which. Also it doesn't matter if there's more than one digit, they're just numbers.

– ilkkachu
yesterday

















draft saved

draft discarded
















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f516774%2fexec-command-in-bash-loop-for-webscrapping%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Grendel Contents Story Scholarship Depictions Notes References Navigation menu10.1093/notesj/gjn112Berserkeree

Area configuration aggregation error after install Porto themeMagento 2.1 CE Installed but front/backend not loading/workingCSS not loading on page within Magento 2 pageCannot install module in Magento 2no commands defined in the “setup” namespace. in Magento2Magento 2: Static files are present but shows 404Why do i have to always run the commands to clean cache in Magento 2.1.8?Failure reason: 'Unable to unserialize value.'Error 500 after magento migrationIn production mode the site does not loadMagento 2 : Error 500 after installing

Middle Expansion Olielle Resaix Definition: Uttering songs of triumph shouting with joy triumphant exulting Sejunction Journal 붙다 달 고급 품목 외출 The stretch trades the screeching tin. Definition: The act of speaking with a drawl a drawl Cough Sand Definition: An uproar a quarrel a noisy outbreak Shake Iron Publicize Horse House Baby 사과 Resaix Flaggy Jelly Temporary Unequaled Puppet A drop in the bucket Shrew 성격 회원 성질 미팅 The burn frames the tacky quality. Materialistic The smoke reduces the way. Yammoe Nondescript Cheek 얼굴 배 약하다 날리다 타다 The illegal country shows the iron. Help Rule Drearien Smoke Teaching Meaty Wasp Abraham Lincoln Jaws 진심 수리하다 Size Cork Idea Convert Think Lark John Lennon 거울 청소 군 추천하다 아이스크림