<p>On the UNIX bash shell (specifically Mac OS X Leopard) what would be the simplest way to copy every file having a specific extension from a folder hierarchy (including subdirectories) to the same destination folder (without subfolders)?</p>

<p>Obviously there is the problem of having duplicates in the source hierarchy. I wouldn't mind if they are overwritten.</p>

<p>Example: I need to copy every .txt file in the following hierarchy</p>

<pre><code>/foo/a.txt
/foo/x.jpg
/foo/bar/a.txt
/foo/bar/c.jpg
/foo/bar/b.txt
</code></pre>

<p>To a folder named 'dest' and get:</p>

<pre><code>/dest/a.txt
/dest/b.txt
</code></pre>

[{'answer_id': 27625, 'author': 'Magnus Hoff', 'author_id': 2971, 'author_profile': 'https://Stackoverflow.com/users/2971', 'pm_score': 7, 'selected': True, 'text': "<p>In bash:</p>\n\n<pre><code>find /foo -iname '*.txt' -exec cp \\{\\} /dest/ \\;\n</code></pre>\n\n<p><code>find</code> will find all the files under the path <code>/foo</code> matching the wildcard <code>*.txt</code>, case insensitively (That's what <code>-iname</code> means). For each file, <code>find</code> will execute <code>cp {} /dest/</code>, with the found file in place of <code>{}</code>.</p>\n"}, {'answer_id': 27747, 'author': 'Stephen Darlington', 'author_id': 2998, 'author_profile': 'https://Stackoverflow.com/users/2998', 'pm_score': 4, 'selected': False, 'text': '<p>The only problem with Magnus\' solution is that it forks off a new "cp" process for every file, which is not terribly efficient especially if there is a large number of files.</p>\n\n<p>On Linux (or other systems with GNU coreutils) you can do:</p>\n\n<pre><code>find . -name "*.xml" -print0 | xargs -0 echo cp -t a\n</code></pre>\n\n<p>(The -0 allows it to work when your filenames have weird characters -- like spaces -- in them.)</p>\n\n<p>Unfortunately I think Macs come with BSD-style tools. Anyone know a "standard" equivalent to the "-t" switch?</p>\n'}, {'answer_id': 58521, 'author': 'agnul', 'author_id': 6069, 'author_profile': 'https://Stackoverflow.com/users/6069', 'pm_score': 1, 'selected': False, 'text': "<p>As far as the man page for cp on a FreeBSD box goes, there's no need for a -t switch. cp will assume the last argument on the command line to be the target directory if more than two names are passed.</p>\n"}, {'answer_id': 58536, 'author': 'Jon Ericson', 'author_id': 1438, 'author_profile': 'https://Stackoverflow.com/users/1438', 'pm_score': 2, 'selected': False, 'text': "<p>If you really want to run just one command, why not cons one up and run it?  Like so:</p>\n\n<pre><code>$ find /foo  -name '*.txt' | xargs echo | sed -e 's/^/cp /' -e 's|$| /dest|' | bash -sx\n</code></pre>\n\n<p>But that won't matter too much performance-wise unless you do this a lot or have a ton of files.  Be careful of name collusions, however.  I noticed in testing that GNU cp at least warns of collisions:</p>\n\n<pre><code>cp: will not overwrite just-created `/dest/tubguide.tex' with `./texmf/tex/plain/tugboat/tubguide.tex'\n</code></pre>\n\n<p>I think the cleanest is:</p>\n\n<pre><code>$ find /foo  -name '*.txt' | xargs -i cp {} /dest\n</code></pre>\n\n<p>Less syntax to remember than the -exec option.</p>\n"}, {'answer_id': 3228414, 'author': 'Rob Styles', 'author_id': 389473, 'author_profile': 'https://Stackoverflow.com/users/389473', 'pm_score': 4, 'selected': False, 'text': '<p>The answers above don\'t allow for name collisions as the asker didn\'t mind files being over-written.</p>\n\n<p>I do mind files being over-written so came up with a different approach. Replacing each / in the path with - keep the hierarchy in the names, and puts all the files in one flat folder.</p>\n\n<p>We use find to get the list of all files, then awk to create a mv command with the original filename and the modified filename then pass those to bash to be executed.</p>\n\n<pre><code>find ./from -type f | awk \'{ str=$0; sub(/\\.\\//, "", str); gsub(/\\//, "-", str); print "mv " $0 " ./to/" str }\' | bash\n</code></pre>\n\n<p>where ./from and ./to are directories to mv from and to.</p>\n'}]
['https://Stackoverflow.com/questions/27621', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2954/']