find -exec
is a commonly used command. However, some people might not be awared of the command find -execdir
and their differences. In this article, we will explain the 2 differences between them.
1. ‘find -exec’ and ‘find -execdir’ execute commands in different directories
find -exec
executes the commands in the starting directory, whereas find -execdir
executes the commands in the directories containing the matched target.
Command | Execute commands in |
---|---|
find -exec | the starting directory |
find -execdir | the directories containing the matched target |
Let’s demonstrate the above idea with an example:
- Create the following structure.
noob@learnfromnoobs:~$ tree find-test/ find-test/ ├── dir1 │ └── myfile1 └── dir2 z └── myfile2 2 directories, 2 files
You can use these commands to create the structure above.
$ mkdir find-test $ mkdir find-test/dir1 $ mkdir find-test/dir2 $ touch find-test/dir1/myfile1 $ touch find-test/dir2/myfile2
- Run
find -exec
under find-test.noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -exec ls -l \; total 8 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir1 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir2 total 8 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir1 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir2
The find command found the the files ‘myfile1’ and ‘myfile2’. As there were 2 matches, the
ls
command was executed twice in the starting directory (find-test) twice. That’s why we are seeing thels
result under find-test twice. Run
find -execdir
under find-test.noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -execdir ls -l \; total 0 -rw-rw-r-- 1 noob noob 0 Jan 27 09:55 myfile1 total 0 -rw-rw-r-- 1 noob noob 0 Jan 27 09:55 myfile2
We get this result because we are executing
ls
in the directories containing the matched target (dir1 and dir2). We are seeing thels
result under dir1 and dir.For more information, please refer to the man page of find.
If you are still not convinced with the above results, you can always use echo to check what the matched target really is.
noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -exec echo {} \; ./dir1/myfile1 ./dir2/myfile2 noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -execdir echo {} \; ./myfile1 ./myfile2
As we can see, the current directory for the
find -exec
command is ~/find-test. For thefind -execdir
command, the current directories are ~/find-test/dir1 and ~/find-test/dir2, which are the directories containing the targets myfile1 and myfile2.
Important
Before executing the command, it is always good to use -ls
to visually inspect the actual files that you are really working on. You never want to remove any files by accident.
noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -ls;
524517 0 -rw-rw-r-- 1 noob noob 0 Jan 27 09:55 ./dir1/myfile1
524518 0 -rw-rw-r-- 1 noob noob 0 Jan 27 09:55 ./dir2/myfile2
2. ‘find -execdir’ does not allow ‘.’ in $PATH environment variable
According to the find command man page,
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.
When using find -execdir
, it is not allowed to have a ‘.’ in $PATH environment variable. (Some people like to put a ‘.’ in $PATH so that they don’t have to type ‘./’ when executing their programs in the current directory. This is highly not recommended. See this article if you want to know more.)
Just for experimental purposes, we can test how find -execdir
would respond if there is a ‘.’ in our $PATH environment variable.
- Add a dot to our $PATH environment variable.
noob@learnfromnoobs:~/find-test$ export PATH=$PATH:. noob@learnfromnoobs:~/find-test$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:.
- Let’s see if
find -exec
would complain or not.noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -exec ls -l \; total 8 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir1 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir2 total 8 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir1 drwxrwxr-x 2 noob noob 4096 Jan 27 09:55 dir2
The command was executed without a problem.
find -exec
allows us to have a ‘.’ in $PATH. Let’s see if
find -execdir
would complain or not.noob@learnfromnoobs:~/find-test$ find . -name 'myfile*' -execdir ls -l \; find: The current directory is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove the current directory from your $PATH (that is, remove ".", doubled colons, or leading or trailing colons)
Oops! Obviously,
find -execdir
really doesn’t like having a ‘.’ in $PATH. The command was not allowed to be executed.
Conclusion
In summary, there are 2 difference between find -exec
and find -execdir
:
find -exec
executes the commands in the starting directory, whereasfind -execdir
executes the commands in the directories containing the matched target.find -execdir
does not allow ‘.’ in $PATH environment variable
I hope you enjoyed this article and learned something new.
Keep learning and have fun!