Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm not very familiar with all the tricks of grep/find/awk/xargs quite yet.

I have some files matching a particular pattern, say *.xxx. These files are in random places throughout a certain directory. How can I find all such files, and move them to a folder in my home directory on Unix (that may not exist yet)?

share|improve this question
4  
You've got to take care when talking about "file type". In unixy environments, the ".xxx" example isn't even an extension in the Windows sense. ".xxx" just constitutes a suffix of the file name. "File type" is more one of a few categories: regular file, device file, symbolic link, directory, named pipe, Unix-family socket, maybe a few others. –  Bruce Ediger Feb 2 '12 at 22:13
    
See also: unix.stackexchange.com/questions/7027/… –  jasonwryan Feb 2 '12 at 22:16
    
@BruceEdiger thanks I guess I really meant "filename pattern" –  qodeninja Feb 3 '12 at 1:14
    
@jasonwryan thanks! –  qodeninja Feb 3 '12 at 1:14
add comment

3 Answers

up vote 10 down vote accepted
mkdir ~/dst
find source -name "*.xxx" -exec mv -i {} -t ~/dst \;
share|improve this answer
1  
I would use mv -i -t ~/dst {} + –  enzotib Feb 3 '12 at 6:56
add comment

If you want to move all the files inside a directory hierarchy to a single destination directory, in bash ≥4 (put shopt -s globstar in your ~/.bashrc) or zsh:

mkdir ~/new-directory
mv -i **/*.xxx ~/new-directory

In other shells:

mkdir ~/new-directory
find . -name '*.xxx' -exec mv -i {} ~/new-directory \;

How to read this find command:

  • .: traverse the current directory
  • -name '*.xxx': act on files whose name matches this pattern
  • -exec … \;: perform this command on each file, replacing {} by the path to the file

There's a more complex command using find that's faster if you have many files as it doesn't need to invoke a separate mv process for each file:

find . -name '*.xxx' -exec sh -c 'mv -i "$@" "$0"' ~/new-directory {} +

The + at the end tells find to invoke the command on multiple files at a time. Since find can only put the file names at the end of the command line, and mv needs to have the destination directory last, we use an intermediate shell to rearrange the arguments ("$0" is the first argument to the shell, ~/new-directory, and "$@" are the subsequent arguments coming from find's expansion of {}).

share|improve this answer
add comment

If you want to replicate the directory structure of the matching source files to the new target directory, you can make use of GNU cp's --parents option:

mkdir /path/to/target_dir
cd source_dir
find . -name '*.xxx' -exec cp -iv --parents -t /path/to/target_dir {} +
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.