help-bash
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]