Is there a way to get find
to execute a function I define in the shell? For example:
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
The result of that is:
find: dosomething: No such file or directory
Is there a way to get find
's -exec
to see dosomething
?
Jak's answer above is great but has a couple of pitfalls that are easily overcome:
This uses null as a delimiter instead of a linefeed, so filenames with linefeeds will work. It also uses the
-r
flag which disables backslash escaping, without it backslashes in filenames won't work. It also clearsIFS
so that potential trailing whitespaces in names are not discarded.For those of you looking for a bash function that will execute a given command on all files in current directory, I have compiled one from the above answers:
Note that it breaks with file names containing spaces (see below).
As an example, take this function:
Say I wanted to change all instances of hello to world in all files in the current directory. I would do:
To be safe with any symbols in filenames, use:
(but you need a
find
that handles-print0
e.g., GNUfind
).Processing results in bulk
For increased efficiency, many people use
xargs
to process results in bulk, but it is very dangerous. Because of that there was an alternate method introduced intofind
that executes results in bulk.Note though that this method might come with some caveats like for example a requirement in POSIX-
find
to have{}
at the end of the command.find
will pass many results as arguments to a single call ofbash
and thefor
-loop iterates through those arguments, executing the functiondosomething
on each one of those.The above solution starts arguments at
$1
, which is why there is a_
(which represents$0
).Processing results one by one
In the same way, I think that the accepted top answer should be corrected to be
This is not only more sane, because arguments should always start at
$1
, but also using$0
could lead to unexpected behavior if the filename returned byfind
has special meaning to the shell.Not directly, no. Find is executing in a separate process, not in your shell.
Create a shell script that does the same job as your function and find can
-exec
that.For reference, i avoid this scenario using:
Get Output of find in current script file and iterate over the output as you may want. I do agree with accepted answer, but i don't want to expose function outside of my script file.
Add quotes in
{}
as shown below:This corrects any error due to special characters returned by
find
, for example files with parentheses in their name.