Timeline for Understanding the -exec option of `find`
Current License: CC BY-SA 4.0
47 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Jul 24, 2024 at 15:35 | comment | added | Praveen Lobo |
@Kusalananda Sure. If I'm not passing any or know exactly how many arguments & know to start at $0 at the risk of readability. Otherwise there will be unnecessary code to figure out the number of arguments. If anyone else is testing this, please note that with + you must have {} and it must appear by itself to avoid errors "find: missing argument to `-exec'" and "find: In ‘-exec ... {} +’ the ‘{}’ must appear by itself, but you specified <cmd>" respectively. At least in find (GNU findutils) 4.8.0
|
|
| Jul 24, 2024 at 15:13 | comment | added | Kusalananda♦ |
@PraveenLobo Of course, you don't need to add that first sh argument after the inline script if you're not passing any arguments to the script. But if you do pass arguments and wants to use them in the script, then you'd better add a string (for example sh) for the $0 argument (not part of the $@ list), or what you think is your first argument will actually be the second.
|
|
| Jul 24, 2024 at 15:08 | comment | added | Praveen Lobo |
@Kusalananda Would you be so kind to give an example of that? I tried to by deliberately failing a command but I don't see any difference with or without sh. I suspect the scenario you mention is not as simple as failing a command. The only difference I see is when shell variables such as $#, $*, or $@ are involved along with + for many arguments.
|
|
| Mar 7, 2024 at 17:23 | comment | added | Kusalananda♦ |
@Chris That string is used in error messages that the sh -c shell may produce. Making it the string sh or find-sh or some similar string is common to be able to distinguish diagnostic output from that sh -c shell invocation from any other diagnostic output that a script (or the utilities used in a script) might possibly produce.
|
|
| Mar 7, 2024 at 15:52 | comment | added | Chris |
If the final sh can be any text, or indeed any value, just to displace the rest to $1+, why is it almost always sh? I find using sh here confusing as it looks like a shell invocation, as if $0 must be an executable.
|
|
| Aug 8, 2022 at 9:45 | review | Suggested edits | |||
| Aug 8, 2022 at 13:28 | |||||
| Apr 22, 2022 at 23:49 | comment | added | Kusalananda♦ |
@midnite You would need to use $1 in place of $name. Other than that, it would be functionally equivalent but would start sh -c once for each found name rather than batching found names and running sh -c as few times as possible.
|
|
| Apr 22, 2022 at 23:43 | comment | added | midnite |
Very nice answer. For the last example, is it the same if we use ; instead of + and without the for-loop? That is find . -type f -name '*.txt' -exec sh -c 'mv "$name" "${name%/*}/done-texts/${name##*/}.done"' sh {} ';'. What are the differences?
|
|
| Mar 8, 2022 at 19:16 | comment | added | Robin A. Meade |
Optimization: Reverse the order of the predicates -type f -name '*.txt' to be -name '*.txt' -type f. Doing so would avoid applying -type f "which potentially involves an extra expensive lstat() system call" when name does not match *.txt, per answer to a different question.
|
|
| Feb 22, 2021 at 10:13 | history | edited | Stéphane Chazelas | CC BY-SA 4.0 |
added 321 characters in body
|
| Jul 9, 2020 at 6:52 | comment | added | Kusalananda♦ |
@Atralb Yes, that would also have worked and had the same effect as the last piece of code, but instead of running mv in a loop, once per found file, you execute both sh and mv for each found file, which will be noticeably slower for large amounts of files.
|
|
| Jul 8, 2020 at 22:58 | comment | added | Atralb |
@Kusalananda Wouldn't your last example also work with this simpler command : find . -type f -name '*.txt' -exec sh -c "mv $1 $(dirname $1)/done-texts/$(basename $1).done" sh {} ';' ?
|
|
| Dec 19, 2019 at 7:47 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 61 characters in body
|
| Jul 7, 2019 at 18:27 | comment | added | bit |
@Kusalananda , I find my self in need of understanding the -exec and execdir options of find, so excuse me for commenting on an old answer but I have a question. In your example for -execdir, how are you guaranteeing that the subdirectory done-texts exist in the same directory where a .txt file is found? Or is your reasoning that -exec will exit with a non zero failure status when the subdirectory done-texts is not in the same directory as a .txt file meaning .txt files will only be moved by mv when the done-texts subdirectory is in the same directory as a .txt file?
|
|
| Jun 7, 2019 at 19:21 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 16 characters in body
|
| Mar 16, 2019 at 21:47 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
deleted 199 characters in body
|
| Nov 1, 2018 at 13:59 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 43 characters in body
|
| Jul 7, 2018 at 12:06 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 7 characters in body
|
| Jul 7, 2018 at 8:55 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 107 characters in body
|
| Jul 7, 2018 at 8:36 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 3669 characters in body
|
| Jul 4, 2018 at 12:42 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 18 characters in body
|
| Jun 25, 2018 at 8:55 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
deleted 12 characters in body
|
| Jun 3, 2018 at 20:34 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 6 characters in body
|
| Jun 3, 2018 at 20:28 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 134 characters in body
|
| Jun 3, 2018 at 20:23 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 134 characters in body
|
| Jun 3, 2018 at 20:14 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 10 characters in body
|
| May 26, 2018 at 8:29 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 54 characters in body
|
| May 5, 2018 at 18:30 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
added 2 characters in body
|
| May 5, 2018 at 18:17 | history | edited | Kusalananda♦ | CC BY-SA 4.0 |
deleted 16 characters in body
|
| Apr 26, 2018 at 20:45 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 81 characters in body
|
| Sep 26, 2017 at 11:30 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 34 characters in body
|
| Sep 26, 2017 at 11:25 | comment | added | Stéphane Chazelas |
You could clarify that all the find arguments after -exec and up to ; or + make up the command to execute along with its arguments, with each instance of a {} argument replaced with the current file (with ;), and {} as the last argument before + replaced with a list of files as separate arguments (in the {} + case). IOW -exec takes several arguments, terminated by a ; or {} +.
|
|
| Sep 26, 2017 at 11:08 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
deleted 32 characters in body
|
| Sep 26, 2017 at 11:06 | comment | added | Kusalananda♦ | @StéphaneChazelas I tried to not be too technical at the start. This is clarified (I hope) by the "footnote". I will adjust it to "external utility". | |
| Sep 26, 2017 at 11:03 | comment | added | Stéphane Chazelas |
Saying it's a shell command is wrong here, find -exec cmd arg \; doesn't invoke a shell to interpret a shell command line, it runs execlp("cmd", "arg") directly, not execlp("sh", "-c", "cmd arg") (for which the shell would end up doing the equivalent of execlp("cmd", "arg") if cmd was not builtin).
|
|
| Sep 26, 2017 at 10:02 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 13 characters in body
|
| Sep 1, 2017 at 16:09 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 291 characters in body
|
| Sep 1, 2017 at 14:51 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 6 characters in body
|
| Sep 1, 2017 at 12:01 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 105 characters in body
|
| Sep 1, 2017 at 11:49 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 9 characters in body
|
| Sep 1, 2017 at 11:32 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 181 characters in body
|
| Sep 1, 2017 at 10:07 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 17 characters in body
|
| Sep 1, 2017 at 8:59 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 917 characters in body
|
| Sep 1, 2017 at 8:33 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 38 characters in body
|
| Sep 1, 2017 at 8:28 | vote | accept | Zsolt Szilagy | ||
| Sep 1, 2017 at 8:26 | history | edited | Kusalananda♦ | CC BY-SA 3.0 |
added 488 characters in body
|
| Sep 1, 2017 at 8:18 | history | answered | Kusalananda♦ | CC BY-SA 3.0 |