Why you don't read lines with “for” in bash?












7















I've read that using "for" is not a good way to read lines in bash.
Many people says this is clumsy and inefficient at best, and fails in many cases.



I'd like to know what is the best way to read lines in bash. Thanks.



For example:



$ for i in $(<afile); do echo "$i"; done









share|improve this question




















  • 1





    Do you have an example of a bash script you've written using "for"?

    – L2G
    Dec 1 '11 at 17:39











  • for example: $ for i in $(<afile); do echo "$i"; done

    – Kyrol
    Dec 1 '11 at 17:51
















7















I've read that using "for" is not a good way to read lines in bash.
Many people says this is clumsy and inefficient at best, and fails in many cases.



I'd like to know what is the best way to read lines in bash. Thanks.



For example:



$ for i in $(<afile); do echo "$i"; done









share|improve this question




















  • 1





    Do you have an example of a bash script you've written using "for"?

    – L2G
    Dec 1 '11 at 17:39











  • for example: $ for i in $(<afile); do echo "$i"; done

    – Kyrol
    Dec 1 '11 at 17:51














7












7








7


4






I've read that using "for" is not a good way to read lines in bash.
Many people says this is clumsy and inefficient at best, and fails in many cases.



I'd like to know what is the best way to read lines in bash. Thanks.



For example:



$ for i in $(<afile); do echo "$i"; done









share|improve this question
















I've read that using "for" is not a good way to read lines in bash.
Many people says this is clumsy and inefficient at best, and fails in many cases.



I'd like to know what is the best way to read lines in bash. Thanks.



For example:



$ for i in $(<afile); do echo "$i"; done






bash readline






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 7 '13 at 5:59









Karan

49.4k1489161




49.4k1489161










asked Dec 1 '11 at 17:30









KyrolKyrol

52951533




52951533








  • 1





    Do you have an example of a bash script you've written using "for"?

    – L2G
    Dec 1 '11 at 17:39











  • for example: $ for i in $(<afile); do echo "$i"; done

    – Kyrol
    Dec 1 '11 at 17:51














  • 1





    Do you have an example of a bash script you've written using "for"?

    – L2G
    Dec 1 '11 at 17:39











  • for example: $ for i in $(<afile); do echo "$i"; done

    – Kyrol
    Dec 1 '11 at 17:51








1




1





Do you have an example of a bash script you've written using "for"?

– L2G
Dec 1 '11 at 17:39





Do you have an example of a bash script you've written using "for"?

– L2G
Dec 1 '11 at 17:39













for example: $ for i in $(<afile); do echo "$i"; done

– Kyrol
Dec 1 '11 at 17:51





for example: $ for i in $(<afile); do echo "$i"; done

– Kyrol
Dec 1 '11 at 17:51










1 Answer
1






active

oldest

votes


















17














You are talking about for line in $(cat file); do and similar constructs. This is:




  • Inefficient because bash has to spawn a subshell and execute cat, read cat's output – the entire file – into memory, parse it (which is the slowest part), only then iterate over all data

  • Unreliable because bash performs word-splitting on the data – not only does it split on newline characters, but also on anything in $IFS (spaces, tabs...)


(If you use $(<...) instead of $(cat ...), you save two milliseconds on Linux, but all other downsides remain.)



A much better option is to use read in a while loop:



while read -r line; do
echo "Input: $line"
done < myfile.txt


Or from a program:



cat file1 file2 file3 |
while read -r line; do
echo "Input: $line"
done


This only reads as much as is needed, does not perform unnecessary processing but allows custom field splitting, and is many times faster and less resource-demanding on large files.



If you're trying to work with the output of find, you should use the same pattern:



find . -name "foo" -type f -print0 | while read -r -d '' file; do
echo "File: $file"
done


See also:




  • Greg's Wiki. Why you don't read lines with "for"

  • Greg's Wiki. Bash FAQ #001: How can I read a file line-by-line?






share|improve this answer


























  • Very nice answer! You showed me what I wanted understand! thanks!

    – Kyrol
    Dec 2 '11 at 13:04











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
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: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
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%2fsuperuser.com%2fquestions%2f363559%2fwhy-you-dont-read-lines-with-for-in-bash%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









17














You are talking about for line in $(cat file); do and similar constructs. This is:




  • Inefficient because bash has to spawn a subshell and execute cat, read cat's output – the entire file – into memory, parse it (which is the slowest part), only then iterate over all data

  • Unreliable because bash performs word-splitting on the data – not only does it split on newline characters, but also on anything in $IFS (spaces, tabs...)


(If you use $(<...) instead of $(cat ...), you save two milliseconds on Linux, but all other downsides remain.)



A much better option is to use read in a while loop:



while read -r line; do
echo "Input: $line"
done < myfile.txt


Or from a program:



cat file1 file2 file3 |
while read -r line; do
echo "Input: $line"
done


This only reads as much as is needed, does not perform unnecessary processing but allows custom field splitting, and is many times faster and less resource-demanding on large files.



If you're trying to work with the output of find, you should use the same pattern:



find . -name "foo" -type f -print0 | while read -r -d '' file; do
echo "File: $file"
done


See also:




  • Greg's Wiki. Why you don't read lines with "for"

  • Greg's Wiki. Bash FAQ #001: How can I read a file line-by-line?






share|improve this answer


























  • Very nice answer! You showed me what I wanted understand! thanks!

    – Kyrol
    Dec 2 '11 at 13:04
















17














You are talking about for line in $(cat file); do and similar constructs. This is:




  • Inefficient because bash has to spawn a subshell and execute cat, read cat's output – the entire file – into memory, parse it (which is the slowest part), only then iterate over all data

  • Unreliable because bash performs word-splitting on the data – not only does it split on newline characters, but also on anything in $IFS (spaces, tabs...)


(If you use $(<...) instead of $(cat ...), you save two milliseconds on Linux, but all other downsides remain.)



A much better option is to use read in a while loop:



while read -r line; do
echo "Input: $line"
done < myfile.txt


Or from a program:



cat file1 file2 file3 |
while read -r line; do
echo "Input: $line"
done


This only reads as much as is needed, does not perform unnecessary processing but allows custom field splitting, and is many times faster and less resource-demanding on large files.



If you're trying to work with the output of find, you should use the same pattern:



find . -name "foo" -type f -print0 | while read -r -d '' file; do
echo "File: $file"
done


See also:




  • Greg's Wiki. Why you don't read lines with "for"

  • Greg's Wiki. Bash FAQ #001: How can I read a file line-by-line?






share|improve this answer


























  • Very nice answer! You showed me what I wanted understand! thanks!

    – Kyrol
    Dec 2 '11 at 13:04














17












17








17







You are talking about for line in $(cat file); do and similar constructs. This is:




  • Inefficient because bash has to spawn a subshell and execute cat, read cat's output – the entire file – into memory, parse it (which is the slowest part), only then iterate over all data

  • Unreliable because bash performs word-splitting on the data – not only does it split on newline characters, but also on anything in $IFS (spaces, tabs...)


(If you use $(<...) instead of $(cat ...), you save two milliseconds on Linux, but all other downsides remain.)



A much better option is to use read in a while loop:



while read -r line; do
echo "Input: $line"
done < myfile.txt


Or from a program:



cat file1 file2 file3 |
while read -r line; do
echo "Input: $line"
done


This only reads as much as is needed, does not perform unnecessary processing but allows custom field splitting, and is many times faster and less resource-demanding on large files.



If you're trying to work with the output of find, you should use the same pattern:



find . -name "foo" -type f -print0 | while read -r -d '' file; do
echo "File: $file"
done


See also:




  • Greg's Wiki. Why you don't read lines with "for"

  • Greg's Wiki. Bash FAQ #001: How can I read a file line-by-line?






share|improve this answer















You are talking about for line in $(cat file); do and similar constructs. This is:




  • Inefficient because bash has to spawn a subshell and execute cat, read cat's output – the entire file – into memory, parse it (which is the slowest part), only then iterate over all data

  • Unreliable because bash performs word-splitting on the data – not only does it split on newline characters, but also on anything in $IFS (spaces, tabs...)


(If you use $(<...) instead of $(cat ...), you save two milliseconds on Linux, but all other downsides remain.)



A much better option is to use read in a while loop:



while read -r line; do
echo "Input: $line"
done < myfile.txt


Or from a program:



cat file1 file2 file3 |
while read -r line; do
echo "Input: $line"
done


This only reads as much as is needed, does not perform unnecessary processing but allows custom field splitting, and is many times faster and less resource-demanding on large files.



If you're trying to work with the output of find, you should use the same pattern:



find . -name "foo" -type f -print0 | while read -r -d '' file; do
echo "File: $file"
done


See also:




  • Greg's Wiki. Why you don't read lines with "for"

  • Greg's Wiki. Bash FAQ #001: How can I read a file line-by-line?







share|improve this answer














share|improve this answer



share|improve this answer








edited Feb 19 at 9:12









slhck

162k47448471




162k47448471










answered Dec 1 '11 at 17:45









grawitygrawity

241k37510566




241k37510566













  • Very nice answer! You showed me what I wanted understand! thanks!

    – Kyrol
    Dec 2 '11 at 13:04



















  • Very nice answer! You showed me what I wanted understand! thanks!

    – Kyrol
    Dec 2 '11 at 13:04

















Very nice answer! You showed me what I wanted understand! thanks!

– Kyrol
Dec 2 '11 at 13:04





Very nice answer! You showed me what I wanted understand! thanks!

– Kyrol
Dec 2 '11 at 13:04


















draft saved

draft discarded




















































Thanks for contributing an answer to Super User!


  • 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%2fsuperuser.com%2fquestions%2f363559%2fwhy-you-dont-read-lines-with-for-in-bash%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

Index of /

Tribalistas

Listed building