0

When using the find program with the -execdir option, I have seen people say the {} will be replaced with the directory and the + with the filename, but the manual does not say what these do. Is there some official documentation that explains this? Also I want to know if they get expanded as relative or absolute paths. I tried creating a script that would take the {} and the + as parameters and save their contents to separate files. I assumed they would get passed as two separate parameters and this would allow me to see how each one is expanded, but the results I am getting make it seem only a single parameter is being passed to the script, so I still can't completely prove to myself what these are and how they are expanded.

Here is the command I am running: find '/home/jesse/hacking/sh_sandbox' -type f -execdir /home/jesse/hacking/sh_sandbox/save_params.sh {} +

The save_params.sh script is an executable shell script with the following code:

echo $0 >> /home/jesse/hacking/sh_sandbox/zero_param.txt
echo $1 >> /home/jesse/hacking/sh_sandbox/first_param.txt
echo $2 >> /home/jesse/hacking/sh_sandbox/second_param.txt
echo $3 >> /home/jesse/hacking/sh_sandbox/third_param.txt

The zero_param text file gets filled with the name of the script that is executing, which is expected. The first_param.txt file is getting filled with ./filename with different filenames. Both the second_param and third_param text files are filled with blank lines each with the same number of lines as the other files. This is what leads to me to believe there is no second parameter being passed to save_params.sh.

1

+ is the end marker , {} is replaced with the filenames the current directory is the path.

so

  • $PWD = /home/jesse/hacking/sh_sandbox/
  • $0 = /home/jesse/hacking/sh_sandbox/save_params.sh
  • $1 = ./zero_param.txt
  • $2 = ./first_param.txt
  • $3 = ./second_param.txt
  • $4 = ./third_param.txt

or something like that... re-reading the question it seems that the script is written to modify the directory that's being searched by find, so what really happens may be more complex.

on the first run there's only one file found

  • $PWD = /home/jesse/hacking/sh_sandbox/
  • $0 = /home/jesse/hacking/sh_sandbox/save_params.sh
  • $1 = ./save_params.sh

so the files would be created with content to reflect that.

  • Quite. OP: change the end marker to ; and check out the difference then re-read the docs. – James Youngman May 22 '16 at 8:39
1

find ... -execdir command {} + doesn't do anything like that.

It works exactly the same as find ... -exec except that find first changes directory to the dir that the matching file(s) are in before executing the command.

Run man find (or if using GNU find, info find or pinfo find for more detailed documentation) and search for -execdir.

From the GNU find man page:

-execdir command ;

-execdir command {} +

Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find. This a much more secure method for invoking commands, as it avoids race conditions during resolution of the paths to the matched files.

As with the -exec action, the + form of -execdir will build a command line to process more than one matched file, but any given invocation of command will only list files that exist in the same subdirectory.

If you use this option, you must ensure that your $PATH environment variable does not reference .; otherwise, an attacker can run any commands they like by leaving an appropriately-named file in a directory in which you will run -execdir.

The same applies to having entries in $PATH which are empty or which are not absolute directory names. If find encounters an error, this can sometimes cause an immediate exit, so some pending commands may not be run at all.

The result of the action depends on whether the + or the ; variant is being used; -execdir command {} + always returns true, while -execdir command {} ; returns true only if command returns 0.

Note that, even though the man page extract doesn't mention it, the ; has to be escaped as \; if run from a shell command-line or script, so that the shell doesn't interpret it as the end of the find command, instead of being passed as an arg to find to indicated the end of find's -exec command. The + doesn't need to be escaped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.