On 5/22/19 10:47 AM, Greg Wooledge wrote: > On Wed, May 22, 2019 at 05:34:22PM +0000, Charles-Henri Gros wrote: >> On 5/22/19 5:43 AM, Greg Wooledge wrote: >>> Standard disclaimers apply. Stop using unquoted variables and these >>> bugs will stop affecting you. Nevertheless, Chet may want to take a >>> peek. >> What unquoted variables? Are you talking about the "$()" expansion? > Yes. I used a variable instead of a command substitution to make it > easier to reproduce the problem. Both have the same behavior in this > case.
That's what I find a bit surprising (but shells are complicated, so maybe this is right. All I know is that the code used to work). I didn't think glob expansions applied to command expansions. All I want here is word split (which is why I can't use quotes) > >> The problem I'm trying to solve is to iterate over regex-escaped file >> names obtained from a "find" command. I don't know how to make this >> work. It works with other versions of bash and with other shells. > First step: do not "regex-escape" them, whatever that means. Just use > the actual filenames as printed by find -print0. > >> The original is closer to something like this: >> >> for file in $(find ... | sed 's/\$/\\$/g'); do grep -e "$file" >> someinput; done > Yeah, that's just the wrong approach. It's also the first thing on > the BashPitfalls page[1] (for a good reason). > > You have two choices here: > > 1) Use find -exec. > > find ... -exec grep -e someinput /dev/null {} + > > 2) Use find -print0 and a bash while read loop. (NOT a for loop.) > > find ... -print0 | > while IFS= read -rd '' file; do > something "$file" > done > > (A variant of this uses < <() instead of a pipeline, so that the while > loop runs in the main shell and variable assignments can persist.) > > Since you only show a simple grep as your action, find -exec is a better > choice for this problem. (Assuming you didn't fatally misrepresent the > problem.) Calling grep once for every file would be inefficient. I don't think I fatally misrepresented the problem, however I do think that you fatally misunderstood it (FWIW I know about -print0 and xargs -0) The file name is the regex (argument to "-e"), not the file "grep" reads. I want to check that some text file contains a reference to a file. But it looks like this would work: for file in $(find ...); do grep -e "$(echo -n "$file" | sed 's/\$/\\$/g')" someinput; done -- Charles-Henri Gros