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;
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
add a comment |
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
1
Just for the record, you don't need that lastexecat 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
add a comment |
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
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
bash shell-script regular-expression file-descriptors exec
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 lastexecat 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
add a comment |
1
Just for the record, you don't need that lastexecat 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
add a comment |
2 Answers
2
active
oldest
votes
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)
2
In Bash 4 you could also usereadarray arr < pgtoscrapinstead of writing a loop. Or evencurl -s https://unix.stackexchange.com/ | readarray arrto directly read thecurloutput into an array.
– BlackJack
May 2 at 16:15
1
OP presumably intended to restore FD0by writingexec 0<&10 10<&-, and accidentally omitted the&ending up with0<10.
– mtraceur
yesterday
add a comment |
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.)
Now, I understand the FD, so it's almost the same as a closingcase,ifstatementesac,fiso 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? so9<&0will end with0&<99<&-Overall, usingmapfile -t arris far better approach I guess for Bash 4.
– Rakib Fiha
yesterday
@RakibFiha, no, it'd still be0<&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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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)
2
In Bash 4 you could also usereadarray arr < pgtoscrapinstead of writing a loop. Or evencurl -s https://unix.stackexchange.com/ | readarray arrto directly read thecurloutput into an array.
– BlackJack
May 2 at 16:15
1
OP presumably intended to restore FD0by writingexec 0<&10 10<&-, and accidentally omitted the&ending up with0<10.
– mtraceur
yesterday
add a comment |
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)
2
In Bash 4 you could also usereadarray arr < pgtoscrapinstead of writing a loop. Or evencurl -s https://unix.stackexchange.com/ | readarray arrto directly read thecurloutput into an array.
– BlackJack
May 2 at 16:15
1
OP presumably intended to restore FD0by writingexec 0<&10 10<&-, and accidentally omitted the&ending up with0<10.
– mtraceur
yesterday
add a comment |
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)
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)
edited May 2 at 14:41
answered May 2 at 14:30
InianInian
5,5901632
5,5901632
2
In Bash 4 you could also usereadarray arr < pgtoscrapinstead of writing a loop. Or evencurl -s https://unix.stackexchange.com/ | readarray arrto directly read thecurloutput into an array.
– BlackJack
May 2 at 16:15
1
OP presumably intended to restore FD0by writingexec 0<&10 10<&-, and accidentally omitted the&ending up with0<10.
– mtraceur
yesterday
add a comment |
2
In Bash 4 you could also usereadarray arr < pgtoscrapinstead of writing a loop. Or evencurl -s https://unix.stackexchange.com/ | readarray arrto directly read thecurloutput into an array.
– BlackJack
May 2 at 16:15
1
OP presumably intended to restore FD0by writingexec 0<&10 10<&-, and accidentally omitted the&ending up with0<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
add a comment |
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.)
Now, I understand the FD, so it's almost the same as a closingcase,ifstatementesac,fiso 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? so9<&0will end with0&<99<&-Overall, usingmapfile -t arris far better approach I guess for Bash 4.
– Rakib Fiha
yesterday
@RakibFiha, no, it'd still be0<&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
add a comment |
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.)
Now, I understand the FD, so it's almost the same as a closingcase,ifstatementesac,fiso 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? so9<&0will end with0&<99<&-Overall, usingmapfile -t arris far better approach I guess for Bash 4.
– Rakib Fiha
yesterday
@RakibFiha, no, it'd still be0<&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
add a comment |
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.)
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.)
answered May 2 at 16:37
ilkkachuilkkachu
63.7k10104183
63.7k10104183
Now, I understand the FD, so it's almost the same as a closingcase,ifstatementesac,fiso 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? so9<&0will end with0&<99<&-Overall, usingmapfile -t arris far better approach I guess for Bash 4.
– Rakib Fiha
yesterday
@RakibFiha, no, it'd still be0<&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
add a comment |
Now, I understand the FD, so it's almost the same as a closingcase,ifstatementesac,fiso 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? so9<&0will end with0&<99<&-Overall, usingmapfile -t arris far better approach I guess for Bash 4.
– Rakib Fiha
yesterday
@RakibFiha, no, it'd still be0<&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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
1
Just for the record, you don't need that last
execat 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