Dave, how can I flatten a directory structure? I’ve got a directory “foo”, with many more sub-directories and files within. I want to take all the files from all levels beneath foo and put them in foo itself.
I’ve tried this: find . *.mp3 -print0 | xargs -0 mv . but I get an error on the mv command that I can’t figure out. Help!
You’re definitely on the right path here. To extract all files in a subdirectory the find command is the correct program, and using the Mac-specific extension “-print0” coupled with the xargs “-0” lets you handle those annoying filenames with spaces in them.
There are two problems with what you have here, though: first off, the syntax of mv is essentially move a to b, but you’re ending up supplying the arguments in the wrong order, because xargs appends the filenames to what you specify, essentially creating “mv . folder/file1 folder/file2”, etc. You can see where that’s going to confuse the command!
The second problem is a bit more subtle: as the program proceeds, I wouldn’t bet that the ‘.’ is going to be interpreted properly and I would strongly suggest that instead you specify the directory name of your target anyway.
Unfortunately, the xargs man page is pretty darn confusing and doesn’t help much. What you want to do is use the -J flag, specify a pattern (or single character), then embed that in the subsequent command. Everwhere the pattern appears, it’ll be replaced by the stream of filenames produced by the find command.
This’ll make more sense with an example, so let’s jump in!
$ pwd /Users/taylor/Desktop/foo $ find . -type f -name "*mp3" -print0 | \ xargs -0 -J% mv % /Users/taylor/Desktop/foo $
That will do what you seek. When you’re ready to delete all the now-empty directories, don’t forget you can use find again, just specify -type d to match directories but not files.