I have to move some files from one folder to another, criteria set by a find and grep. When I try to move the files it breaks.

The actual move it's trying is mv /somefolder/export//somefolder/storage/testfileOLD.txt

What I expected was mv /somefolder/storage/testfileOLD.txt /somefolder/export/testfileOLD.txt

The command I'm using:

find /somefolder/storage/ -type f -name "*OLD*" -newermt '2019-05-1' ! -newermt '2019-06-7' -exec grep -qiF 'closed' {} \; -exec mv {} /somefolder/export/{} \;

I already tried with -exec basename {}, this gives me the right result, but when I modify the mv to

-exec echo {} /somefolder/export/$(basename {}) \;

to check if it works it still gives me the /somefolder/export//somefolder/storage/testfileOLD.txt.

  • Do you need the {} in destination for mv? It should work fine if you just leave it as -exec mv {} /somefolder/export/ \; – deimos Jun 5 at 14:19

$(basename {}) will fail (better: just be an empty string). The subshell invoked here does not expand {} to the filename as this is specific to find and not exported into the subshell your command creates.

You can test this by running

find -exec echo "this will be empty:" $(basename '{}') \;

I suggest you write a small script:

mv "$1" /somefolder/export/"$( basename ${1})"

and run it in your find command:

find /dir/ <specs> -exec grep -qiF 'closed' '{}' \; -exec bash script.sh '{}' \;

AFAIK the behaviour of forwarding '{}' to subshells depends on your find-version.

  • Updated - I had focused on how to circumvent '{}' for more complex commands in find – Fiximan Jun 5 at 14:00
  • 1
    thanks, I used your idea, but used the inline sh -c for this to work -exec sh -c 'mv {} /somefolder/export/$(basename "$1")' sh {} as this will not add extra scripts on the server (even one that can be deleted directly afterwards) – Joris D R. Jun 5 at 14:18

If you want to retain the original structure below directory /somefolder/somedir, you could use rsync instead of mv.

Test setup:


Expected result after move:


The commands:

# first, create a file list of relative paths (some arguments removed for simplicity)
$ find /somefolder/storage -type f -name "*OLD*" -printf '%P\n' > /tmp/filelist

# cat to illustrate its content
$ cat /tmp/filelist

# then rsync using `--remove-source-files` to move the files 
$ rsync -av --remove-source-files --files-from=/tmp/filelist /somefolder/storage /somefolder/export

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.