Try the execdir
option for find
: it executes the command you specify in the directory of the file, using only its basename as the argument
From what I gather, you want to create "a" and "b" in the "main" directory. We can do that by combining $PWD
and the -execdir
option. Have a look at the solution below. (The && find … ls
parts are for output only, so you can see the effects. You'll want to use the command before the &&
.)
First, I set up the testing environment:
-----[ 15:40:17 ] (!6293) [ :-) ] janmoesen@mail ~/stack
$ mkdir test && touch test/{a,b} && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:40 ./
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:40 ./test/b
This is what happens when you use a simple -exec
— the original files are touched:
-----[ 15:40:30 ] (!6294) [ :-) ] janmoesen@mail ~/stack
$ find test -type f -exec touch {} \; && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:40 ./
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:40 ./test/b
However, if we combine $PWD
with the argument placeholder {}
and use -execdir
, we achieve what (I think) you want:
-----[ 15:40:57 ] (!6295) [ :-) ] janmoesen@mail ~/stack
$ find test -type f -execdir touch "$PWD/{}" \; && find . -exec ls -dalF {} +
drwxr-xr-x 3 janmoesen janmoesen 4096 2012-05-31 15:41 ./
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:41 ./a
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:41 ./b
drwxr-xr-x 2 janmoesen janmoesen 4096 2012-05-31 15:40 ./test/
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:40 ./test/a
-rw-r--r-- 1 janmoesen janmoesen 0 2012-05-31 15:40 ./test/b
find . -name 'foo-exclude-me' -prune -o -name 'foo*' -print
With no -print
, the implicit default action applies to every match, even pruned ones. The explicit -print
applies only under the specified conditions, which are -name 'foo*'
only in the else branch of -name 'foo-exclude-me'
.
Generally speaking, use an explicit -print
whenever you're doing something more complex than a conjunction of predicates.
Your second attempt with ! -path './foo-exclude-me/*'
didn't work because ./foo-exclude-me
doesn't match ./foo-exclude-me/*
(no trailing /
). Adding ! -path ./foo-exclude-me
would work.
Best Answer
I think I would do it this way:
Based on @StephaneChazelas' feedback I believe this method would eliminate the extraneous searching into any
/p/
directories:Analyzing a find
To compare find commands you can add the debug switch
-D search
so that you can see how a particular find would perform vs. another.I ran @StephaneChazelas' command vs. mine to see where the differences were. The 2 commands are run and their output is run into an
sdiff
below:If you notice, there's a gap in Stephane's approach that mine doesn't have. Even with the prune. I think this shows that his method is avoiding extra work in walking into directories that it should otherwise be ignoring.