If you ever want to see how well someone knows unix (e.g. in an interview), you could ask them this question:
You have a directory containing a lot of files and subdirectories, and you want to copy all of them except for the directory called big_dir. How do you do it?
Here's my solution (select the text to make it visible):
cp -r `ls | grep -v big_dir` dest_dir
Here's another one:
Remove read and execute priviledges from the files you don't want to copy, then proceed as normal
Posted on February 16, 2004 05:33 PM
More programming articles
The first solution fails in the pathological case of another file matching /big_dir/, as well as in the less uncommon case where the directory is huge. The second modifies the [meta]data... which may or may not be okay.
Of course, part of the unix spirit is knowing when pathologies can be ignored: in most cases they'll sure both be good enough!
I'd do
ls | xargs perl -MFile::Copy -ne 'next if $_ eq "big_dir"; copy $_, "other_dir" or warn "cp:$_:$!"'
Except that File:Copy doesn't handle directories :)
Posted by: Gaal Yahas at February 16, 2004 05:52 PMfind . ! -name "big_dir" -print0 | xargs -0 -i{} cp -pr {} other_dir
takes care of it.
Posted by: Mark A. Hershberger at February 16, 2004 06:15 PMHmmm … I would do:
tar --exclude big_dir/ -cf - | (cd dest_dir ; tar xvf - )
Preserves ownership, permissions, etc and excludes that nasty ol' big directory.
Posted by: Sean Conner at February 16, 2004 09:43 PMI use zsh. Here's one of the reasons why:
mkdir dest_dir
cp -R source-dir/^big_dir dest_dir
(In zsh's glob syntax, the pattern "^foo" matches "all files except foo".) Make it cp -p -R if you care about preserving modes/owners/etc.
Posted by: Doug L. at February 17, 2004 01:05 PMI like for loops, so:
for f in * ; do if [ "$f" != big_dir ] ; then cp -r $f ../to/ ; fi ; done
Somehow I don't think windows people have quizes like these :-)
Posted by: B. Johannessen at February 17, 2004 09:02 PMMy solution: mv the big_dir away, cp -r, mv the directory back.
Advantage: relatively fast, only uses cp and mv, size of big_dir doesn't matter (as long as the mv is within the same filesystem, of course)
Disadvantage: you need some place to mv the big_dir to and the current directory's modification time is changed, even though it didn't really change.
So many different solutions... isn't unix great?
PS. In my opinion, the solution above using find is the "correct" one.
Posted by: Jorrit Wiersma at February 18, 2004 08:48 AMB. Johannessen: In windows you open then window, hit Ctrl-A, and shift click on all the items you don't want. Then drag & drop to the destination with the correct modifiers to make a + appear on the cursor. I mean, sure there's a CLUI but windows no longer considers it the primary way of doing stuff.
In NT the for loop answer should work too.
Posted by: Jesse at February 18, 2004 01:38 PMJesse: You seem to have missed my point. The point I was trying to make was that windows has one (or at most a few) easy/practical ways of solving a problem. Unix, on the other hand, often allows you to solve the same problem in what sometimes seems like an infinite number of ways. That's one of the things I (and I suspect many others) love Unix systems, and feel confined when having to work in windows.
Posted by: B. Johannessen at February 18, 2004 10:10 PMJohannessen,
when you say "unix" you mean "find", "grep", and "ls" right?
I tend to be a OS atheist, so to me tools are not the OS and vice versa.
find . -print | grep -w big_dir/ | cpio -pdumvB other_dir
Posted by: ArizonaEd at April 4, 2004 10:29 PMdaniel is purple and there is not enough poon
Posted by: jesse at June 15, 2004 06:46 PMThis is when copying is done from level where files and Directories to be copied exist.
For Dest_dir Directory at same level where the all the files and dirs to be copied exist:
cp -pr `ls -F|grep -v 'big_dir/'|grep -v 'dest_dir/'` dest_dir
For Dest_dir is at one or more levels above level of files and directories to be copied:
cp -pr `ls -F|grep -v 'big_dir/'` dest_dir
Shortcoming of this method is if dest_dir is inside any directory which is to be copied then it will go into loop and will system space full
Posted by: Harish Kumar at November 6, 2004 01:40 AMcp -pr `ls -F|grep -v 'big_dir/'|grep -v 'dest_dir/'` dest_dir
Above can be written as:
cp -pr `ls -F|grep -v 'big_dir/|dest_dir/'` dest_dir
Sorry,
This should be
cp -pr `ls -F|egrep -v 'big_dir/|dest_dir/'` dest_dir
Heh nice solutions everybody. I actually will use one of them, don't know which one yet for my backup script I am writing. Thanks!
Posted by: Designer at January 12, 2005 04:53 PMhow abt symbolic links? i guess cp wud create copies files. if u want to copy symbolic links. use tar and untar
Posted by: arun at August 7, 2005 04:05 AMWonder if you could lend some help with a problem. I am tring to copy files from a disk on another disk except I want to leave out a directory and all its files. I am using a SGI host computer. The normal operations that I follow to copy from one disk to another is this..
find . -mount -depth -print | cpio -pdm /mnt3
This copies all the directories and files but I want to leave out a directory and all its files say named eng_load I have tried this
find . ! -name eng_load -mount -print | cpio -pdm /mnt3. This sill encludes the directory eng_load. I have also tried this...
find . ! -name eng_load -prune -print | cpio -pdm /mnt3. Still does not work.
and ideas????
Thanks
Tom