|
|
How do I flatten a directory structure in Unix?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. Good luck!
Related Mac OS X Help articles:
✔ Audacity can't find LAME library, I can't save Mp3?
Hey Dave. I read your article Audacity can't save mp3 audio files and am still puzzled because I downloaded the LAME Mp3 converter...
✔ How to remove Dashboard as a "space" in Mac OS X Spaces?I'm a big fan of the Spaces utility in Mac OS X that lets me have multiple virtual screens [see Set Up Mac...
✔ Best place to buy a cheap MacBook laptop?Hi Dave. I am looking for two gently used MacBook laptops for my teen daughters. Personal computers would greatly facilitate their studies as...
✔ File too big error copying to USB flash drive on my Mac?I'm baffled. I have a 16GB Kingston USB flash drive that I use on my Mac system and I'm trying to copy a...
✔ Stealth image capture photo from webcam on my Mac?Someone sneaks into my cubicle while I'm at lunch and takes candy out of my desk. Petty, but stupid too. I want to...
Let's stay in touch!
Sign up for my weekly AskDaveTaylor Newsletter and you'll receive even more tech and gadget help
right to your inbox, along with exclusive news and industry updates. It's good stuff. I promise!
Categorized:
Mac OS X Help
,
Unix and Linux Help
(Article 3875,
Written by Dave Taylor)
Tagged: Previous: How do I create a JavaScript countdown timer on my Web page? Next: How can I watch PAL DVDs on a regular NTSC TV? Reader Comments To Date: 13Phil said, on January 31, 2005 11:17 PM:
Thanks for responding! OK, that looks great, but -print0 is implemented on my Suse 9.1 box just fine (not a Mac!). Also, -J isn't implemented in Suse 9.1, so I'm still stuck. I'd also add `pwd` to the end so as to not have to hard code the destination so it can be put in a shell script. Avi said, on February 1, 2005 3:02 AM:
Linux also has -print0 in find and -0 in xargs. -J is not in Linux but I guess that --replace can be used instead. The one qustion I have though is why not use find . -type f -name "*.mp3" -exec cp {} \ instead of find and xargs? Dave Taylor said, on February 1, 2005 3:09 AM:
Good point, Avi, but you ironically demonstrate why I avoid the curly brace notation in find by your mistake: In fact, you need to escape the curly braces AND you need to have an escaped semicolon too for it to work properly, as in: find . -type f -name "*.mp3" -exec cp \{\} /Users/taylor/Desktop/foo \; A good solution, though, if you're willing to fiddle around and get the backslashes right. :-) Dave Taylor said, on February 1, 2005 3:52 AM:
"I'd like to make a cron job that backs up only the protected iTunes music files in my iTunes directory complete with directory structure." I don't know what "protected" means in this context, but I'll say that if you want to back up an entire directory structure, you can typically use either cp -R or cpio (use 'man cpio' to see how this useful program works). Phil said, on February 1, 2005 2:12 PM:
Here's the final, working command for linux: find . -type f -name "*mp3" -print0 | xargs -0 --replace=% mv % `pwd` Dave Taylor said, on February 1, 2005 2:25 PM:
Great. Thanks for coming back and completing the loop. I knew that the GNU version of xargs had to have some solution to this. Ken said, on February 1, 2005 6:06 PM:
"Protected" in the context "protected iTunes music files" refers to files of type .m4p, which are AAC files (ordinarily .m4a) that are "protected" with Apple's Playfair DRM wrapper. Dave Taylor said, on February 1, 2005 6:55 PM:
Okay, Ken, this is new to me, even though I'm a big fan of my two iPods and iTunes on all my Macs. Are you asking if there's a way to unprotect the files and/or defeat the Playfair DRM? David Rouse said, on February 12, 2005 5:37 PM:
Um ... how about using the Finder? In the Finder, File:Find... Search in: "Specific Places" Click on "Add" button and choose the foo folder Search for items whose name ends with .mp3 The select all the results and drag them to foo. Dave Taylor said, on February 12, 2005 6:24 PM:
David, I don't think that'll work because he's trying to pull files from lots of different subdirectories at the same time, and even in "list" view the Finder has a tendency to want to move the folders that files are in when you do large multi-directory grabs... Anacreo said, on March 2, 2005 8:14 PM:
The 'find | xargs' examples should run a lot faster then a 'find ... --exec' operation as you'd have to create one process for each file as opposed to xargs which will make as few processes as possible based on the length of the data on the stdin. On Solaris I usually will do something like 'find ... | sed -e "s/.*/'&'/g" | xargs ...'. This will wrap each line in single quotes. Keep up the good tips. monsieur said, on May 17, 2006 5:18 AM:
-print0 is a GNU/BSD extension !
I do have a comment, now that you mention it!Check This Out Too... |
Recent Entries
Look for Answers
Recommended
All Our Categories
Apple iPad Help
Articles and Reviews Auctions and Online Shopping Blogs and Blogging Building Web Site Traffic Business and Management Computer and Internet Basics d) None of the Above Facebook Help Google Gmail Help Google Plus Help HTML, JavaScript and Web Site Programming Industry News and Trade Shows iPhone and Cell Phone Help iPod, Sony PSP and MP3 Player Help Kindle Fire Help Mac OS X Help Pay Per Click (PPC) Advertising Pinterest Help Search Engine Optimization (SEO) Shell Script Programming Tech Support Video Help The Writing Business Twitter, LinkedIn and Social Network Help Unix and Linux Help Video Game Tips and Help Windows PC Help Find Me on Google+ ADT on G+ |
How about one step further?
I'd like to make a cron job that backs up only the protected iTunes music files in my iTunes directory complete with directory structure. I've tried various cp commands and never can seem to figure it out.
How would you go about doing that?