5 ms·
Recursively find all Emacs backup files and remove them find . -name '~' | xargs rm* Recursively find all Python files and search them for the word ‘import’ fi
by sabat 15y ago
Recursively find all Emacs backup files and remove them
find . -name '~' | xargs rm*
Recursively find all Python files and search them for the word ‘import’
find . -name '.py' | xargs grep 'import'*
Hmm. I don't mean to be a tweak, but you don't need xargs to do either of those things. Just:
find . -name '~' -delete
find . -name '.py' | grep 'import'
Note: I can't figure out how to get an asterisk to show up, and don't have time to look it up.
- ptramo 15y agoNo. You're looking for files having import in their path here, not in their contents.
- sjs 15y agoHe got the command wrong but his point stands: find . -name '.py' -exec grep -H import '{}' \;
- Jach 15y agoIn addition to ptramo, you really want: grep 'import' `find -name '* .py'`
- ptramo 15y agoWell, you want xargs as soon as your project is big, because you'll reach the limits on arguments fairly quickly. I won't go too deep on the issues this will trigger if your filenames contain special characters. We often think of spaces, but you could have some nastier stuff. If you want to sound smart at your next geeks reunion, simply read http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html http://www.dwheeler.com/essays/fixing-unix-linux-filenames.h...
- Jach 15y agoOf course, I meant my version as an alternative to xargs. And I think you have about 128k of space for the filenames, but yeah with large projects that can be a problem. Thanks for the link, that's more interesting than the submission. :)
- ptramo 15y agoFair point, I just submitted it :)
- derobert 15y agoOn (modern, i.e. 2.6.23 and later) Linux at least, you won't hit them quickly: $ getconf ARG_MAX 2097152 and if you do hit them, they're very easy to raise: $ ulimit -s 32768 $ getconf ARG_MAX 8388608 xargs is still useful for its other features, of course.
- ptramo 15y ago# echo "2097152/$(echo "/my/still/quite/reasonable/path/to/a/file"|wc -c)"|bc 49932 linux-2.6 # git ls-files|wc -l 36747 Getting close! :) And I would guesstimate (Linux, kernel >= 2.6.23) to still be a fairly small amount of the machines people interact with professionally through a command line. And if in a script/snippet, you often want to cover a vast majority of the systems you _could_ end up with. Won't be System III, at least for me, but there has to be a RHEL5 system in a closet right? :)
- LukeShu 15y ago
- MostAwesomeDude 15y agoOr maybe, if you have GNU grep: $ grep -R --include=\*.py import .
- cstejerean 15y agoYou are correct about -delete. You could also use -exec to execute arbitrary commands for each file returned by find. I needed some examples however, and I often see "find | xargs" because people don't know, or forget, the options to find. I should write a follow up post on find.
- yason 15y agoNobody remembers the various command line switches of find or grep. I use xargs quite often because it's a very simple concept and I know how to mix and merge any commands together with it and that's something I've only had to to go ahead and learn once.
- baddox 15y agoThe grep one didn't involve a switch on grep. It was just the xargs example with xargs removed.
- cstejerean 15y agoThe grep one is also wrong as it does an entirely different thing without xargs.
- nuxi 15y agoThe -delete option is not available on all UNIX systems, as it's not part of the POSIX spec (http://pubs.opengroup.org/onlinepubs/009604599/utilities/find.html http://pubs.opengroup.org/onlinepubs/009604599/utilities/fin...). (Also, rant rant, I really don't understand why find was extended with -delete in the first place. What's next, "ls --delete" or maybe "cat --grep"?)
- RexRollman 15y agoI did a quick look online to see who has it. GNU, DragonFly BSD, NetBSD, and FreeBSD all have a -delete option. OpenBSD seems to be the only one that doesn't (although its online manpage does give examples on how to do it with -exec and piping to xargs).
- nuxi 15y agoThat's basically two flavours of UNIX (Linux and BSD), but that's OK - others are unfortunately either dead or dying. The UNIX family tree (http://www.levenez.com/unix http://www.levenez.com/unix) has been shrinking so rapidly in the last few years, that the current situation looks like the early years.
- RexRollman 15y agoSince the BSDs are all independently developed, I don't consider them to be one Unix, even though they share ancestry.
- jfb 15y agoThe orthogonality ship has sailed with Unix, for better or (IMHO) for worse. The Unix Haters were right about this, among other things, and the sections of the handbook about the shell are still valid, even as time and Moore have rendered others quaint.
- nuxi 15y agoFor worse, I concur. I still fire up my SGI boxes once in a while to remind myself things didn't use to/don't have to be as binary as they mostly are today (Linux vs BSD, iOS vs Android, Intel vs AMD etc.). That, and to run electropaint, of course. =)
- ori_b 15y agofind . -name '.py' | grep 'import' I don't think that works. That'll grep for files named '\import\',
- beambot 15y agoI use xargs for the find + rm cases he mentions. However, if you just want the file names containing the words import, I rely exclusively on grep: grep -r -l import *.py
- bradleyland 15y agoI'm not an expert by any means, so please provide correction/feedback if I'm wrong, but I've read that xargs is more efficient because it can send parameters to the cmd in batches. I've read this in contrast to `-exec {}` not `-delete`, however. For example: find . -name '*~' -exec 'rm {}' The statement above executes `rm result` for every result. By contrast: find . -name '*~' | xargs rm The example above would group the results and pass them to rm like this: rm result1 result2 result3 result4 Because I'm not an expert, I don't know how many parmeters it will pass, or if initiation of many new processes has a significant performance impact on newer systems. I would suspect that for anything involving the disk, I/O will be the bottle neck, not process turn-up time. Anyone have an opinion/insight?
- LukeShu 15y ago-delete will be the fastest because find can do everything, and it already has the file loaded, and doesn't have to do a second lookup. -exec will be slower because for each file it has to spawn a new process (this is where most of the time goes), and then that new process has to look up the file. xargs will be faster than -exec because it will collect a few hundred, or thousand, filenames, and pass them all to one command (the article claims 4096 is the default, on some systems it may be lower). This means that typically, only 3 processes need to spawn: `find', `xargs', and one `rm'; instead of find, and many, many `rm's. Now, xargs is still slower than -delete because it will buffer the filenames, either waiting for the list to end, or 4000 filenames to pass to `rm'. Then, rm must look up the file from the filename. To make my point I just set up a test situation with 1110 files ending with `~', among a total of 2221 files. I tested how fast it is to delete all the files ending with `~' using the 3 following commands: $ find . -name '*~' -delete $ find . -name '*~' -exec rm {} \; $ find . -name '*~' -print0 | xargs -0 rm | real | user | sys -delete | 0.024s | 0.003s | 0.020s -exec | 0.819s | 0.007s | 0.107s xargs | 0.073s | 0.007s | 0.017s I probably should have run those tests multiple times, and taken the average, but meh.
- bradleyland 15y agoVery cool. Thanks for the insight. Mind if I ask how you timed execution? The take aways for me are: * Use find's built-in options where possible * Use xargs where a built-in method isn't available * Use -exec only when nothing else will do