4 ms·
No such example; after all, you can spawn a shell subprocess in any of those. There's just certain types of tasks where you can more clearly express your inten
by adrusi 11y ago
No such example; after all, you can spawn a shell subprocess in any of those.
There's just certain types of tasks where you can more clearly express your intent in a shell script. If, for example, you need to spawn a ton of subprocesses, you can do that in any scripting language, but shell is designed from the ground up to launch subprocesses — it's most basic purpose is to launch programs.
And so while I can't give an example of something that can only be done in a shell script, here's a shell script that I wrote a few weeks ago that would have been a pain in the neck to express in any other language:
#!/bin/sh
cd "$(dirname "$0")"
for test in *.in; do
test="$(basename "$test" .in)"
infile="$test.in"
outfile="$test.out"
output="$(./whofrom "$infile" 2>&1)"
expected="$(cat "$outfile")"
if [ "$output" != "$expected" ]; then
echo "Failed test $test"
echo "Expected: $expected"
echo "Actual: $output"
echo
fi
if ! valgrind --error-exitcode=1 --leak-check=full ./whofrom "$infile" 2>/dev/null >/dev/null; then
echo "Failed test $test"
valgrind -q --leak-check=full ./whofrom "$infile"
echo
fi
done
- viraptor 11y agoI don't think it's a big pain in python. I imagine ruby wouldn't be terrible either: #!/usr/bin/env python import sys, os, subprocess, glob os.chdir(os.path.dirname(sys.argv[0])) for test in glob.glob("*.in"): test = os.path.splitext(test)[0] infile = test + ".in" outfile = test + ".out" output = subprocess.check_output(["./whofrom", infile], stderr=subprocess.STDOUT) expected = open(outfile, 'r').read() if output != expected: print("Failed test", test) try: devnull = open(os.devnull, 'w') subprocess.check_call(["valgrind", "--error-exitcode=1", "--leak-check=full", "./whofrom", infile], stderr=devnull, stdout=devnull) except subprocess.CalledProcessError: print("Failed test", test) subprocess.check_call(["valgrind", "-q", "--leak-check=full", "./whofrom", infile]) (since it's a quick script, I'm ignoring stuff like closing files - they'll get GCd on each iteration anyway) Apart from the header, the whole script is pretty much the same when comparing line-by-line.
- jhallenworld 11y agoOne issue is the problem of indirect documentation, and it comes down to this one line: "import sys, os, subprocess, glob". How do you find which module you need? Search on the web may be the best answer. In shell at least you have "man -k". Once I know the module, how do I get its documentation? Here at least there is an answer: import glob; help(glob); But how good is this documentation? If I do it I get: glob(pathname) Return a list of paths matching a pathname pattern. The pattern may contain simple shell-style wildcards a la fnmatch. Already python is telling me that the "man" documentation is going to be better :-).
- viraptor 11y ago> How do you find which module you need? Search on the web may be the best answer. Experience, stdlib reference, web searches. Same as with bash. > In shell at least you have "man -k". I really disagree here. Since you took `glob` as an example, how do you get to the explanation of `for test in *.in`? Go on, try that with "man -k". > Already python is telling me that the "man" documentation is going to be better I'm not trying to say python is good here (well, the stdlib documentation on the web is actually pretty good, it's just not easily available from the console). But the idea that bash/man is more discoverable is just wrong... You can find the glob under "Pattern Matching" section which is all right, but you need to understand most of the expansion mechanism of shell to know it applies to "for". Then again "for" itself has a definition that belongs more to a CS material, than to a usage guide.
- jhallenworld 11y agoWell I agree that glob was not the best example. For sure there are things you have to learn about shell scripting as well.. one of them is if "man for" doesn't work, try "help for" or "man bash". In fact there is no good reason for this and it should be improved. (not to mention that you already had to know what *.in does, but you could argue that this is fundamental shell syntax: man bash / pattern matching).
- adrusi 11y ago