Execute a command where a file is found
If you run this command your touch file
will be run, potentially multiple times, from the directory in which the command has been started:
find -name '*.pdf' -exec touch file \;
On the other hand, if you run this variant, each instance of the command will be run in the target file's directory:
find -name '*.pdf' -execdir touch file \;
In both cases you can see this in action by substituting the touch file
with either echo {}
and/or pwd
.
From manpage:
-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 startedfind
.
You can extract the filename's directory with dirname
and take it from there, something like this:
find . -name "*.pdf" -type f -exec bash myscript {} \;
where the file myscript
contains the following:
dir=$(dirname "$1")
cd "$dir"
touch file
With zsh
you could use glob qualifiers to select e.g. only .pdf
files and via modifiers save the directory names in an array with unique elements and then cd
into each of those directories and run your command. This way you are running your command only once in each directory, irrespective of the number of .pdf
s that were found in that directory:
dirlist=(**/*.pdf(.:a:h))
for d in ${(u)dirlist[@]}
(cd $d && touch file)
or
typeset -U dirlist
dirlist=(**/*.pdf(.:a:h))
for d in ${dirlist}
(cd $d && touch file)
You can further combine modifiers and qualifiers, e.g. to glob for regular files (hidden and non-hidden) with the extension .bkp
and save unique directory names in an array:
dirlist=(**/*.bkp(D.:a:h))