1

I've been googling this, but although I see people using them, I see no explanation for it. I've also tried "find and sed" searches, but again no explanation on these. The sed man and other sed guides out there also don't include it.

Now, I'm using the find command to find several files and then using sed to replace strings whithin the files. I believe that these "{}" and "\;" at the end of the sed are what allows sed to take each file name from find and search through its text. But I'd rather not guess and know for sure what they are and why they're there. Here's my current command:

output=$(find . -type f -name '*.h' -o -name '*.C' -o -name '*.cpp' -o -name "*.cc" -exec sed -n -i "s/ARG2/ARG3/g" {} \;)

I'm also concerned that the ";" at the end may not be necessary since I'm wrapping it also and throwing it into a variable. Could someone clarify what those curlies and backslash are doing and whether I need them?

EDIT: It turns out that they're properties of find -exec, not sed. So I've been looking in the wrong place. Thanks!

GeleiaDeMocoto
  • 151
  • 1
  • 10
  • 2
    those have no meaning to `sed`; their meaning is to `find`. Search for `-exec` in the `find` man page. – Charles Duffy Feb 29 '16 at 23:27
  • BTW, `sed -i` *has* no output on stdout; what's the purpose of trying to capture it? – Charles Duffy Feb 29 '16 at 23:30
  • (Also, all-caps names are reserved for variables with meaning to the system or the shell; see fourth paragraph of http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html for the relevant standard, keeping in mind that shell variables and environment variables share a namespace). – Charles Duffy Feb 29 '16 at 23:31
  • @CharlesDuffy The output that I'm capturing into the variable is from find, not from sed. At least that's the intention. – GeleiaDeMocoto Mar 01 '16 at 00:34
  • @GeleiaDeMocoto, but your `find` action is not to print anything, but to execute `sed`; it *has* no printed-to-stdout output in this use case. – Charles Duffy Mar 01 '16 at 04:56
  • @GeleiaDeMocoto, ...moreover, because filenames can contain any character other than a NUL, and scalar variables can't contain NULs (being C strings, and thus terminated by a NUL), you can't unambiguously store more than one filename in a single shell scalar variable: Even if you take care against whitespace, filenames containing literal newlines will mess you up. Thus, using `foo=$(find ...)` is basically always buggy; the only safe way to store output from `find` in shell variables is to NUL-delimit it and read into an array. – Charles Duffy Mar 01 '16 at 04:58

1 Answers1

4

find has two versions of the -exec action:

-exec ... {} +

...runs the command ..., with as many filenames from the results as possible added at the end.


-exec ... {} ';'

...runs the command ... once per file found, with the filename substituted in place of the {} sigil; it's not mandatory that the sigil be at the end of the line in this usage.


Thus, either a + or ; needs to be passed as a literal argument to find for it to accept the action as valid.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Hmm, what's the difference between "with as many filenames from the results" and "once per file"? – flow2k Apr 13 '20 at 23:01
  • Ah, consulting the man page, the first option adds them as CLI parameters to the command. – flow2k Apr 13 '20 at 23:03