16 ms·
The History of the Design of Unix’s Find Command (1995)
- kazinator 11y agoLet's use ( ) for grouping, instead of [ ], so people have to escape them when using find through a Bourne-like shell: \( \). And what better terminating token for -exec than the semicolon!
- simias 11y agofind was actually introduced several years before the bourne shell, so that's a bit unfair. I assume that the syntax was less awkward when it was first released. Not that I don't agree that it's a pain to use nowadays.
- gauravagarwalr 11y agoI have found the `find` command and its API to be the hardest to learn. 3+ years on *NIX machine, spending close to 70% time on the command line when not browsing, and yet I still am not comfortable with `find`.
- jwdunne 11y agoOnly just getting to grips with it the past year and even then I'm not doing anything in the way of advanced. I have, however, found knowing only a subset of its features has dramatically improved my efficiency at the terminal. Awk and sed have been a useful learn too - I need to check out gawk. Apparently if trying to use awk and grep (emphasis on trying), I should just use gawk.
- cogs 11y agoBlatant plug: My pain at all these unnecessary hieroglyphics & man page work is why I built Crab, so I could use SQL to find things and an EXEC command to run commands on them. etia.co.uk Really it shouldn't have to be this hard.
- jstanley 11y agoInteresting that that's the direction you went with this. I've always wished that mysql supported a more unix-like interface, where a few characters of composable interfaces would do, instead of word after word of semi-natural-language syntax.
- cogs 11y agoWordiness isn't really a problem, because I'm a fast typer and most systems have tab completion and history recall. For me the benefit is that for lots of problems, whether databases or the filesystem, thinking in terms of sets feels really natural. I can't imagine why you'd want to pipe grep results to grep -v rather than say "and not" I guess we all prefer the language whose syntax we know the best.
- rdc12 11y agoI remember seeing Crab a while back on HN, and thinking I don't see why you would want this, but when you mentioned thinking in sets it was way more clear. It may be cause I don't use SQL often that I didn't click. Prehaps that would be a good thing to mention on the website.
- valarauca1 11y agoPersonal Experience: Implement a command line stack machine like an RPN calculator and it'll click. Every argument normally just pop's the next arg to determine its state. I purposely made myself use find for about 6 months and I still struggle with flags sometimes, especially when chaining more complex expressions. Find is nirvana with SSD's. I can throw find commands at the root -exec'ing out to grep on my 512GB SSD very quickly. Lastly cygwin + find is still faster then windows explorer search in my experience, especially if you have an SSD. This is a great way to start teaching yourself unix command line also.
- potatosareok 11y agoNot sure if I'm doing anything wrong but I find cygwin/msys find very slow on my windows SSD. I mean I still generally use it just because I'm familiar but if I'm looking for a file in huge directory I look up whatever flags I need for dir (dir /s something something)
- valarauca1 11y agoIts start up is incredibly slow, its operations are slower then native, but then you aren't doing native things. The argument commonly used is productivity vs speed of operation. Even slow file systems are faster then I can humanly see happen more often then not.
- gregwtmtno 11y agoI combine "find ./" and grep instead of learning how to use find. (I'm a terrible person.)
- bane 11y agoYou mean that's not how you're supposed to use it? It's such an utterly terrible tool and needs replacing bad.
- untothebreach 11y agoI have found it helpful to learn small parts of the `find` api a bit at a time. For example, instead of `find ./ -print | grep "name_of_file"`, I use `find ./ -name "name_of_file"` or `find ./ -name '* name_of_file *"` (without the spaces -- I can't seem to surround text with asterisks without it triggering HNs formatting (yes I tried escaping them)) if you want to fuzzily search for a filename. You can replace `-name` with `-iname` if you want your search to be case-insensitive.
- maw 11y agoFor all I know you may indeed be a terrible person ;), but this isn't why. The composability of Unix' commands is probably its greatest strength.
- marcosdumay 11y agofind . | grep 'abc' === find . -name 'abc' find . | grep -i 'abc' === find . -iname 'abc' Here, saved you a pipe :) (Oh, and with -exec and -delete, not needing that pipe is incredibly useful. Find is an incredibly powerful command.)
- Sodel 11y agoSorry if this is pedantic, but actually: find . | grep 'abc' === find . -name '*abc*' find . | grep -i 'abc' === find . -iname '*abc*' The -name and -iname options do a verbatim file name check if you don't include those wild-card asterisks. I've been inconvenienced by having to go back and add them often enough that this is burned into my brain. :-)
- 11y ago
- to3m 11y agoxargs is worse than find, I'd say, on account of its useless default mode of operation. If it accepted newline-delimited input, it would cater for every non-pathological case, rather than (as it does now) failing miserably on many reasonable file names. (Of course, you have xargs -0 - but not all tools output appropriate data. And it accepts shell-style quoting - but do we really want that contagion to spread?) The bizarre thing is that except for oddities like `echo * | xargs', every tool I've ever met that outputs lists of file names outputs them with newline as the separator. And any that currently don't, would be better off doing that, anyway, I'd argue - since most Unix tools are line-oriented.
- jschwartzi 11y agoxargs is very powerful when you want to run one command with many arguments, but each argument is newline-delimited. That's basically all I use it for, and it saves me a lot of looping and subshell creation. For example, when purging backups from Mercurial after a revert: find . -name *.orig | xargs rm
- icebraining 11y agoBut that's exactly it - if any of the filenames have spaces, that will fail, since xargs will try to delete each part separately. From the man page: Because Unix filenames can contain blanks and newlines, this default behaviour is often problematic; filenames containing blanks and/or newlines are incorrectly processed by xargs.
- johnwfinigan 11y agoExcluding filenames containing newlines, I wonder how many weird corner cases this would reveal: ls | tr '\n' '\0' | xargs -0 rm I've been annoyed by ls and xargs not playing together here and there, but the above only just occurred to me. Not sure if it's a good idea yet or not!
- zb 11y agofind . -name '*.orig' -delete
- vram22 11y agoWhat do you find hard to learn about find? I don't think it's particularly hard to learn, as Unix commands go. A bit more difficult than the average command, maybe. Of course not everything about it may be well designed (as some other comments here say), but that holds true to some extent for any command or language.
- vram22 11y agoI just read the original post (the store about someone writing to Dennis Ritchie) which this comment thread is about. Noticed a mention of find and cpio. So wanted to say: find, in general, is quite a powerful command [1], and one of the ways of using it, is piping its output to cpio or other commands, to act upon the found filenames (which can include relative or full paths, depending on how you call find). There is also the -exec option to find, which can do more or less what I said above (piping find's output to other commands), but without using a pipeline. Those are some good reasons why you might want to persevere and learn to use find, despite its awkward syntax. And it's not really that difficult. [1] One such example is a command I used to use a lot: some variation on piping the output of find to cpio, using the -p option of cpio (for pass, IIRC). E.g.: $ find . -name some_wildcard -print | cpio -pdmuv dirname which would copy an entire directory subtree from one place in the file system to another (or to a place (directory) in a different file system too). (Something like XCOPY ... /s /v /e in DOS.) And those cpio options could be used to do things like keeping the permissions of the target files the same as those of the source, or not, etc. Imagine how much time that could save (over having to later manually change the permissions, after the copy, particularly when there are many files). And that's just one example of the power of fin (along with other Unix commands).
- revscat 11y agoOS X users: check out the mdfind command. It doesn't work on dot directories, but for quickly finding files, I try it first simply because the command syntax is so much easier for me to remember.
- misiti3780 11y agojust tried it out - it caused iterm to crash
- fintler 11y agoTo be fair, iTerm probably caused iTerm to crash.
- misiti3780 11y agovery true!
- yati 11y agoI am on OS X now, but I remember using `locate` on Linux to achieve something similar to OS X `mdfind`
- philh 11y ago> WHAT idiot would program a command so that you have to say -print to print the output to the screen. What IDIOT would make a command like this and not have the output go to the screen by default. You don't need to say -print. It's always printed by default for me, and the man pages (on both linux and OS X) confirm this. > If the expression contains no actions other than -prune, -print is performed on all files for which the expression is true. [linux] > If none of -exec, -ls, -print, -print0, or -ok is specified, the given expression shall be effectively replaced by ( given expression ) -print. [OS X] Has this only been added in the last 20 years?
- KWxIUElW8Xt0tD9 11y agoI have written many cross-platform shell scripts over the years. The -print option may have been made standard by the GNU implementation and then spread -- I don't know -- but at least on some older versions of UNIX you do indeed need to specify -print or it won't.
- vram22 11y agoYes, I think that is true. Speaking from memory, but I've worked on Unix for long, and I think I remember that on some older Unix versions, you had to specify -print, otherwise it would walk the directory tree according the conditions you specified (such as filename wildcards, the -o option (for OR), etc.), but would produce no output for that walk.
- deleted 11y ago[deleted]
- kabdib 11y agoThe -print option was not the default when I first used find (in v6 Unix, back in PDP-11 days). I don't recall what 4.2bsd did, which was the next version of Unix that I used. I thought it was pretty brain-damaged, and that whoever decided that had decided poorly. The author of the tool should have pushed back, IMHO. Then again, I don't know the political structure of the shop where find(1) was written, so maybe that was impossible.
- 11y ago
- bane 11y agoIf you want to take a lesson from this, try your best to fight bad specifications, and if you are in a position to accept or not accept code with a bad interface, don't accept it. Bad code lives forever and find has been a curse on *nixers ever since.
- triangleman 11y agoIs unix shell one of those things you just have to suffer through for 3-6 weeks before "getting it"? Kind of like learning a musical instrument? Also would anyone recommend learning how to use Windows PowerShell and again would that have the same kind of insane learning curve? I'm just asking to make sure I'm not crazy and that command lines do in fact have a very high learning curve. Every time I attempt it, I fail because I don't know how to use these freaking flags and switches, and it's really hard to ask the computer how to use them. And that's if you know which command to use.
- untothebreach 11y agoI hope this doesn't come across as a "RTFM" comment, because I don't intend it to be, but I have found it helpful to get into the habit of reading man files when I need to know how to use a command. The quality of the man files on your system might not be the best, so I would suggest bookmarking the man pages from the OpenBSD project[1]. It might not always be directly applicable to your system, since some commands are different between linux, osx, and *bsd, but no matter what platform you are on, the OpenBSD man pages are very high quality, and at the very least might point you in the right direction. 1: http://nixdoc.net/man-pages/OpenBSD/ http://nixdoc.net/man-pages/OpenBSD/
- niuzeta 11y agoAdding to this comment is my recommendation to bro(http://bropages.org/ http://bropages.org/) command, which is a wiki-like man pages that simply tells you what the comand does on high level, and a few practical examples. man pages are great for the folks who are used to the type of prose and those who want to get to the bottom of the command. But I've almost always found the man pages unhelpful and sometimes even distracting(check the infamous sudoers manpage, which starts off with a 'Quick guide to EBNF). So my advice to those who start on linux is, if man pages aren't good for you, then google! more often than not, the task you're trying to do is something that someone has already tried to do, and there will be an easier-to-understand description than man page.
- 11y ago
- racl101 11y agoI love Unix shell, but I gotta admit, the find command is kind of a mind fück.
- TerryADavis 11y agohttp://www.templeos.org/Wb/Adam/Opt/Utils/Find.html http://www.templeos.org/Wb/Adam/Opt/Utils/Find.html Must handle binary graphics in source code.
- Random_BSD_Geek 11y agofind has a worse reputation than it deserves. Yes, its learning curve is steep; when I was learning Unix, find was one of the commands that really stymied me. But like many powerful tools once you've learned it you can do some wonderful things with it. Here's a random example: Prune a a scratch directory of files older than one week. find /dir -type f -mtime +7 -delete How would you do it without find? (Serious question. I know it can be done with other tools but since I can do it in one line with find I've never bothered to look for another solution.)
- zokier 11y ago> How would you do it without find? (Serious question. I know it can be done with other tools but since I can do it in one line with find I've never bothered to look for another solution.) With python you can do something like [os.unlink(file) for file in [os.path.join(*path_parts) for l in [list(zip(repeat(root),files)) for root,dirname,files in os.walk('/tmp') if len(files) != 0] for path_parts in l] if datetime.fromtimestamp(os.stat(file).st_mtime) < datetime.now() - timedelta(days=7)] ...I suspect there might be bit more elegant solutions too
- monochromatic 11y agoWoof. That is one python program I would not call "executable pseudocode."
- zokier 11y agoMore idiomatic version is more readable but also more verbose: cutoff_date = datetime.now() - timedelta(days=7) for basepath,_,files in os.walk('/tmp'): for filename in files: filepath = os.path.join(basepath, filename) if datetime.fromtimestamp(os.stat(filepath).st_mtime) < cutoff_date: os.unlink(filepath) Python is not really that great when forced to oneliner format, and I'm not really a good code golfer anyways.
- useerup 11y agoIn PowerShell: ls /dir -re | ? LastWriteTime -lt (Get-Date).AddDays(-7) | del i.e. 1: enumerate the files recursively (ls is alias for Get-ChildItem) 2: pipe through a filter (? is alias for Where-Object) that selects only files written to more than 7 days ago 3: pipe those files to the Remove-Item command (del is alias for Remove-Item)
- 336f5 11y agoThis doesn't explain the history of `find`. Saying 'a specification made us do it' is not an explanation, it is passing the buck.
- tragomaskhalos 11y ago"-exec ls -l {} \;" ""{} \;" ?? Whaaaa ?" "Hush child; just type the incantation, and all will be well"
- deleted 11y ago[deleted]