When I run the command

find dir_1 -type f -name 'f*'

I found 2 files there "file_11" and "file_22". Now I want to move those files to another directory "dir_2" using -exec with the "find" command. So I use this command.

find dir_1 -type f -name 'f*' -exec mv {} ../dir2 \;

This command works.

Now, there are also some ".txt" files in the directory "dir_1". I want to move these text files to "dir2" and also rename these files. so I use this command,

find dir_1 -type f -name '*.txt' -exec mv {} ../dir2/new_{} \;

But I am getting the error,

mv: cannot move 'dir_1/file1.txt' to '../dir2/new_dir_1/file1.txt': No such file or directory
mv: cannot move 'dir_1/file2.txt' to '../dir2/new_dir_1/file2.txt': No such file or directory

Can anyone help me.


2 Answers 2

find dir_1 -type f -name '*.txt' -exec \
    sh -c 'echo mv "$1" "/path/to/dir_2/new_${1##*/}"' sh_mv {} \;

the syntax ${parameter##word} is the shell parameter expansion. and cuts-up-to-last-prefix specified by word from its given paramter; here it strips the path part from the filename. so ./dir_1/sub_directory/file1.txt becomes just file1.txt and later added new_ to the filename.

the sh -c '...' construct is known as inline shell (here sh shell) and we open it in order to provide/build necessary parameters for the mv command to move &rename and using its parameter-expansion feature for that.

with sh -c '...' sh_mv {}, it's accepting two arguments, one is sh_mv (used as a label for the inline shell we open (parameter $0)); the {} argument will be the substitution of the fileName found by find command and will pass as next argument (parameter $1).

note: remove echo to perform actual mv which we used for dry-run to test.


{} is replaced by the entire pathname of the file as you see it if you run the command without the -exec part. So obviously, you cannot directly use that. You can use the basename command to strip only the file name of the path, as in

find dir_1 -type f -name '*.txt' -exec sh -c 'mv "{}" ../dir2/new_$(basename "{}")' \;

Adding quotes " around {} will have it work also if the filename contains spaces.

  • Not Working. Same Problem
    – mbx20
    Feb 15, 2020 at 11:26
  • OK, I agree I did not test. Taking inspiration from above, it does work when surrounded by an inline shell construct. Benefit above the accepted answer is that this here is a bit easier to understand.
    – vanadium
    Feb 15, 2020 at 14:22

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.