What happens when you grep the file you've redirected grep to?
anniecherkaev.com
anniecherkaev.com
In other words, it's behaving like a FIFO that persists a history of everything that's been written to it, which also suggests that there are two pointers, one for the read position and another for the write position; all becomes clear when we realise that it's not reading and writing with the same file descriptor, but rather two file descriptors of one file, opened twice.
The tl;dr of why small sizes terminate and large sizes loop infinitely is this: when the size of data output is not enough to fill the write buffer, the read can reach the end of file (0 bytes read), and then it flushes the write buffer before terminating; but when the output size fills the write buffer, it gets flushed and ends up back in the input, causing the infinite loop.
The C stdio buffering layer doesn't guarantee that data written with a fwrite() will show up in a fread() from a different file handle that references the same file (and now that I think about it, that would seem to be quite difficult to guarantee.)
type foo.bat >> foo.bat
https://stackoverflow.com/questions/3398258/edit-shell-scrip... (curiously, the accepted answer is incorrect and downvoted highly)
...and Windows batch files:
https://stackoverflow.com/questions/906586/changing-a-batch-...
I'll try to find some time soon to port that C+inline assembly example to Linux, I didn't know much C or ASM back when I originally asked the question.
grep -r [something] . >foo
I've done this by accident once or twice :-) grep -r [something] * > foo
What I now do instead: grep -r [something] * > .foo
mv .foo foo
Why it works: At least on bash, "*" does not match hidden files (files that begin with "." such as ".foo"). sed 's/a/b/' test.txt > test.txt
After that command the file is empty no matter what was in there before. Instead you have to use the -i flag like: sed 's/a/b/' -i test.txt
And different operating systems seem to behave differently:https://stackoverflow.com/questions/5171901/sed-command-find...
I prefer having a way of reverting changes rather than something that gets in the way.
(It writes to a temporary file, and then atomically renames it to the final location. Whereas if sed expr src > dst is killed, dst may be corrupt. You'd need to handle temporary file management yourself if your script needs to be reliable.)
Anyway sed is so fast you should definitely check the output before overwriting stuff. Same goes for anything on the command line.
Get ZFS. Do snapshots.
That wouldn't really help in the case of redirecting sed to the same file.
$ echo "a" > test.txt
$ sed s/a/b/ test.txt
b
$ sed s/a/b/ test.txt > test.txt
$ cat test.txt
$ sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd
https://joeyh.name/code/moreutils/ >;word Write output to a temporary file. If the command
completes successfully rename it to word, otherwise,
delete the temporary file. >;word cannot be used
with the exec(2) built-in.
¹ e.g. https://www.freebsd.org/cgi/man.cgi?query=ksh93&apropos=0&se...That is not suitable for a program like grep.
Consider for example what should happen when grepping /dev/null/? Or, a more sensible case, piping the output of some command to grep. Grep will read from 'standard in' which is "Just A File" so it just calls read until it reports end of file.
In the solution I gave, same thing as before because I said regular file. That is if you can open /dev/null for reading, which I thought you couldn't.
I think I'd be fine with saying that the infinite loop is the behavior that happens. GNU's grep obviously is doing some janky check which it shouldn't be. Consider what it will do when you get just slightly more clever and it can't determine the input/output types. The one on macOS has arbitrary file size-dependent behavior, which is problematic. Doesn't seem like either of them does a consistent thing.
Gonna blow your mind here: Press up once and then Ctrl-O.
test.txt will contain "a\n" not just "a"
-n to disable adding \n
when I checked on Linux, both `cat` and `grep` give error when input file name is same as output... but not `sed/awk/head/tail/sort/etc`..
A quote for you [0]: Under normal circumstances every UNIX program has three streams opened for it when it starts up, one for input, one for output, and one for printing diagnostic or error messages. These are typically attached to the user's terminal (see tty(4) but might instead refer to files or other devices, depending on what the parent process chose to set up. (See also the "Redirection" section of sh(1).)
here I was specifically checking append, where it doesn't get truncated...
"Quit grepping yourself! Quit grepping yourself!"
#IKnowYourAreButWhoAmI?