[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] /proc/.../cdrom/info not completely read
From: |
Greg Wooledge |
Subject: |
Re: [Help-bash] /proc/.../cdrom/info not completely read |
Date: |
Mon, 30 Apr 2012 09:52:11 -0400 |
User-agent: |
Mutt/1.4.2.3i |
On Mon, Apr 30, 2012 at 08:42:53AM +0200, humpty wrote:
> whatever method I try, bash doesn't read the whole file
>
> $ file=/proc/sys/dev/cdrom/info
> $ while read line...done <"$file"
> only outputs the first line
>
> $ exec {foo}<"$file"
> $ while read -u line
> outputs about six lines, as does
> $ mapfile -t myArray <"$file"
> and
> $ echo "$(<"$file")"
This requires a Linux box, obviously. It's not a real file.
But OK, that is indeed odd. The following commands give what I can only
guess is "the whole thing" (although how can we be sure?):
cat "$file"
cat < "$file"
awk 1 "$file"
awk 1 < "$file"
sed '' "$file"
sed '' < "$file"
But as you say, a while read loop only gives one line, and a mapfile
gives a most interesting result:
arc3:~$ mapfile myarray < "$file"
arc3:~$ declare -p myarray
declare -a myarray='([0]="CD-ROM information, Id: cdrom.c 3.20 2003/12/17
" [1]="
" [2]="drive name: sr0
" [3]="drive speed: 48
" [4]="drive # of slots: 1
" [5]="Can close tray: 1
" [6]="Can op")'
Looks like a buffering issue of some kind. Note how the 6th line is
truncated. (mapfile uses a buffer size of 128 bytes?)
> if I copy "$file" anywhere (say /tmp/) there is no problem any more.
> This happens with BASH 4.2 on Debian, and openSuse (and BASH 3.3.4 on
> archlinux (I've been told))
>
> what could be the reason for such a behaviour?
Some peculiarity in the Linux kernel, I would imagine. What I do not
understand is why bash gets a different result than awk or sed, which
are also reading a line at a time.
Might be useful to play around in C a bit.
arc3:/tmp$ cat foo.c
#include <stdio.h>
main() {
char s[81];
while (fgets(s, 81, stdin) != NULL) {
printf("%s", s);
}
}
arc3:/tmp$ gcc -o foo foo.c
arc3:/tmp$ ./foo < "$file"
CD-ROM information, Id: cdrom.c 3.20 2003/12/17
drive name: sr0
drive speed: 48
drive # of slots: 1
Can close tray: 1
Can open tray: 1
(etc.)
This, too, appears to give "the whole thing". Now let's try something
lower level:
arc3:/tmp$ cat bar.c
#include <unistd.h>
main() {
char s[20];
int n;
while ((n = read(0, s, 20)) > 0) {
write(1, s, n);
}
}
arc3:/tmp$ gcc -o bar bar.c
arc3:/tmp$ ./bar < "$file"
CD-ROM information, arc3:/tmp$
Aha. This is similar to what we saw in mapfile.
Presumably awk and sed and cat and cp are using a buffer size that's
sufficient to hold the "whole thing", whereas bash's buffer size is
not.
In any case, I would count this as an issue with the Linux kernel, not
with bash. As far as workarounds go, you already have one -- make a
copy of it first, using one of the "large buffer" tools.