tag:blogger.com,1999:blog-8908007078853642865.post5721138935067152396..comments2023-10-26T07:55:37.152-05:00Comments on system("rm -rf /");: BASH’s ‘read’ built-in supports '\0' as delimiterRichard Lihttp://www.blogger.com/profile/10372929728933063306noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-8908007078853642865.post-20275272583230800482018-08-02T20:55:25.626-05:002018-08-02T20:55:25.626-05:00find -print0 | while IFS= read -r -d $'\0'...find -print0 | while IFS= read -r -d $'\0' X<br /><br />avoids affecting $IFS outside the loopAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-41471676686537539502017-07-11T19:20:58.671-05:002017-07-11T19:20:58.671-05:00Thanks for the tip! I was playing around with this...Thanks for the tip! I was playing around with this some more and I have a slight possible improvement. In your example, the "while" command runs in a subshell. So if the commands try to set variables, the rest of the script won't see them. Instead, you can make the left hand side run in a subshell instead, like this:<br /><br />while IFS="" read -r -d $'\0' x ; do<br /> echo ">>$x<<"<br /> last_found="$x"<br />done < <( find -name \*.txt -print0 )<br />echo "last_found = $last_found"<br /><br />IFS="" stops the line being read being broken up into words.Anonymoushttps://www.blogger.com/profile/03151009140139478763noreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-79649593555007422562017-07-11T19:16:41.925-05:002017-07-11T19:16:41.925-05:00However, being explicit about it, using -d $'\...However, being explicit about it, using -d $'\0' rather than '', makes it obvious what you're expecting the delimiter to be. Readability!Anonymoushttps://www.blogger.com/profile/03151009140139478763noreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-21445159693821477392014-08-28T17:23:29.688-05:002014-08-28T17:23:29.688-05:00if [[ -z $(read -r -p "Hi there null:" i...if [[ -z $(read -r -p "Hi there null:" imNULL) ]];then<br />echo "true"<br />else<br />echo "you are not nothing you are nothing not even null"<br />fiAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-79281568008615459592014-05-03T06:04:37.791-05:002014-05-03T06:04:37.791-05:00oups, just saw your last paragraph about this ! ;)...oups, just saw your last paragraph about this ! ;) A good lesson that I should read the entire post carefully before answering ;)vaabhttp://vaab.blog.kal.frnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-5450955142485545362014-05-03T06:01:19.515-05:002014-05-03T06:01:19.515-05:00Hi, you're misleaded: $'\0' won't ...Hi, you're misleaded: $'\0' won't ever be a valid command line argument as NUL character is not a valid character for command lines and variable in bash. What happens here is that \0 is silently removed, and what you are doing is:<br /><br />read -r -d '' X<br /><br />which happens to be understood by read as separating on the NUL character. You can try your example by removing $'\0' it'll work the same.<br /><br />Remember: variable and command line argument can't hold NUL characters: they are silently skipped (it's the only char they can't hold). Of course, pipes support all binary data: so you can write or read NUL characters.vaabhttp://vaab.blog.kal.frnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-17966408030769770002014-02-06T09:37:36.002-06:002014-02-06T09:37:36.002-06:00Nice find, but sadly read still trims values, so f...Nice find, but sadly read still trims values, so filenames cannot have spaces at the end:<br /><br />echo -e ' test \0 string ' |<br />{ read -rd '' s; read -rd '' x; echo "-$s- -$x-" | od -tx1z; }<br /><br />0000000 2d 74 65 73 74 2d 20 2d 73 74 72 69 6e 67 2d 0a >-test- -string-.<<br /><br />But sometimes there is a workaround<br /><br />find . -printf "%p.\\0" |<br />while read -rd '' name;<br />do name="${name%.}";<br />echo "-$name-";<br />done <br />Tinohttps://www.blogger.com/profile/04802985702436738056noreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-35796192353954780342013-02-22T08:42:01.645-06:002013-02-22T08:42:01.645-06:00If you don't need to split the line, just its ...If you don't need to split the line, just its whole content (ie. when reading filenames), you can use that:<br /><br />IFS=;<br />find -print0 | while read -r -d $'\0' X<br /><br />Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-38773601723784153682012-11-09T05:27:01.656-06:002012-11-09T05:27:01.656-06:00Thanks, this post helps me much.Thanks, this post helps me much.Andrey Tataranovichhttps://www.blogger.com/profile/08081249568199801233noreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-27020468224295535532012-06-25T08:07:49.736-05:002012-06-25T08:07:49.736-05:00Very useful for reading /proc/$$/cmdlineVery useful for reading /proc/$$/cmdlineAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-91764259719205626872012-05-03T19:10:22.851-05:002012-05-03T19:10:22.851-05:00Hmm, I discovered this same thing today myself, th...Hmm, I discovered this same thing today myself, then I realized: it is still not safe! It appears to handle the null just fine, but it cannot handle trailing newlines, they are still gobbled up. Someone should fix 'read' to not do gobble them when the delimiter is null. <br /><br />The 'readarray' command strangely does support trailing newlines (it actually keeps them in the array), but since it does not support defining an alternate delimiter (such as null) it is of no use!!!<br /><br />But ultimately, it would be better if IFS supported null, then you could actually assign the values to an array without loosing your context (a problem which makes 'readarray' and 'read' way less useful even if they worked properly).Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-87008177082378982762012-02-10T12:57:27.484-06:002012-02-10T12:57:27.484-06:00Don't forget to quote the $x as in "$x&qu...Don't forget to quote the $x as in "$x" :)Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8908007078853642865.post-34525229960820179102010-01-05T16:07:52.438-06:002010-01-05T16:07:52.438-06:00This is fantastic, thank you. I've encountered...This is fantastic, thank you. I've encountered this problem in years past, and have been struggling with it the past couple days. If only bash's "for" loop could be used this way, it would be more elegant.Erichttp://nomeaning.netnoreply@blogger.com