Some time ago, I posted answer to some question about scripting. Someone pointed out that I shouldn't use following command:
for x in $(cat file); do something; done
but instead of that:
while read f; do something; done < file
Usless Use of Cat article suppose to explain the whole problem, but the only explanation is:
The backticks are outright dangerous, unless you know the result of the backticks is going to be less than or equal to how long a command line your shell can accept. (Actually, this is a kernel limitation. The constant ARG_MAX in your limits.h should tell you how much your own system can take. POSIX requires ARG_MAX to be at least 4,096 bytes.)
If I correctly understood this, bash(?) should crash if I use output of very big file in command (it should exceed ARG_MAX define in limits.h file). So I checked ARG_MAX with command:
> grep ARG_MAX /usr/src/kernels/$(uname -r)/include/uapi/linux/limits.h
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
Then I created file containing text with no spaces:
> ls -l
-rw-r--r--. 1 root root 100000000 Aug 21 15:37 in_file
Then I run:
for i in $(cat in_file); do echo $i; done
aaaand nothing terrible happened.
So what should I do to check if/how this whole 'don't use cat with loop' thing is dangerous?
$()
instead of backticks", but you already do. – Henrik supports the community Aug 21 '17 at 14:09for i in $(cat in_file)
doesn't iterate over the lines of the file, it iterates over the words resulting from the contents of the file being subjected to word-splitting and pathname expansion. – chepner Aug 21 '17 at 14:10