Execute on the basename of a find command

basenamecommand linefind

Suppose I have a directory structure as follows

test
test/a
test/b

Now I want to execute a command, such that in the . folder I can execute a command on the basename of the files a and b.

So basically, I want something like this, which I naively tried

find test -type f -exec touch `basename {}` \;

Only, this does not result in empty files a and b in the parent directory. Suppose that my touch command can only take a single argument.

This will result in a directory structure like this

a
b
test
test/a
test/b

I know how to do this in a bash script, but I am interested in single command solution.

Best Answer

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
Related Question