So, I bought this book called Primes and Programming, and it's pretty tough going. Today I wrote this (simple) program from chapter 1:
#!/usr/bin/env python
import math
def find_gcd(a,b):
while b > 0:
r = a - b * math.floor(a/b)
a = b
b = r
return int(a)
if __name__ == "__main__":
import random, sys
while True:
print find_gcd(random.randrange(int(sys.argv[1])), random.randrange(int(sys.argv[2])))
...and just now I called it like so:
./gcd-rand.py 10000 10000 > concievablyreallyhugefile
...and now I'm dreaming of a bash
one-liner that breaks when concievablyreallyhugefile has reached a certain size. I guess it would look something like:
while $(du -h f) < 32M; do ./gcd-rand.py 10000 10000 > $f; done
...but I have never written a while loop in bash
before and I don't really know how the syntax works.
4 Answers 4
The trick is to use the test command test
or the equivalent [ ... ]
:
while [ "$(du -m f|cut -f1)" -lt 32 ]
do
./gcd-rand.py 10000 10000 > "$f"
done
See help test
for more information.
Note
test
or [
command is a bash builtin. The help information can be retrieved inside bash via help test
or help [
.
man test
refers to the test
command that is used if a shell has no such builtin or is invoked explicitly as /usr/bin/test
.
-
-
No - see the added Note in the answer.H.-Dirk Schmitt– H.-Dirk Schmitt2013年03月07日 11:47:45 +00:00Commented Mar 7, 2013 at 11:47
-
Huh.
help
is a Bash-builtin but notzsh
's, for e. g.poige– poige2013年03月07日 12:03:46 +00:00Commented Mar 7, 2013 at 12:03
./gcd-rand.py 10000 10000 | head -c 32M > concievablyreallyhugefile
head
will stop reading after 32MB. Soon after head
stops reading, gcd-rand.py
will receive a SIGPIPE signal and exit.
To avoid storing a truncated last line, as Michael Kjörling noticed:
./gcd-rand.py 10000 10000 | head -c 32M | sed '$d' > concievablyreallyhugefile
-
This. Piping is The Unix Way (tm), and it will give you exactly as much data as you want. Of course, it might break the resulting file in the middle of a number, so in the general case the last line of the file will be meaningless. If you want to guard against that, it'd probably be better to implement output size limiting in the script itself (look up
len()
, and remember to account for the newline).user– user2013年03月09日 23:21:23 +00:00Commented Mar 9, 2013 at 23:21 -
@MichaelKjörling Good point about the last truncated line. Again piping saves the day.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2013年03月10日 16:34:06 +00:00Commented Mar 10, 2013 at 16:34
Your python code loops forever. Thus, you might want to run it in the background and then kill it when the file size is exceeded. As one-liner:
{ ./gcd-rand.py 10000 10000 > f & }; p=$!; while (( $(stat -c %s f) < 33554432 )); do sleep .1; done; kill $p
Note: choose sleep time as appropriate, instead of stat you can also use du, as suggested by Dirk.
-
This is good, but you should use
wc -c
instead ofstat
, which will allow it to work outside of Linux.jordanm– jordanm2013年03月07日 15:23:39 +00:00Commented Mar 7, 2013 at 15:23
You can use the ulimit
command to restrict how large a file the shell (or its children) can create:
ulimit -f 32768
-
I think this qualifies as an excellent example of what Raymond Chen calls "using global state to manage a local problem".user– user2013年03月11日 08:19:56 +00:00Commented Mar 11, 2013 at 8:19
-
Well, it's limited to the current shell, so
(ulimit -f 32768; cmd)
is a possibility.chepner– chepner2013年03月11日 12:33:35 +00:00Commented Mar 11, 2013 at 12:33
man bash
.fractions.gcd
method is useful.