Showing posts with label shell. Show all posts
Showing posts with label shell. Show all posts

BASH’s ‘read’ built-in supports '\0' as delimiter

I thought it was impossible to use '\0' as a delimiter in bash, but noticed yesterday that Gentoo’s ebuild.sh had pipelines like this:
find ..... -print0 |
while read -r -d $'\0' x; do
# Do something with file $x
done

This makes it possible to handle any strange filenames correctly, even if the filename contains newline ('\n') or carriage return ('\r') characters. (Some other commands, including sort and xargs, have options to make null character the delimiter based on the same reason.)

Because BASH internally uses C-style strings, in which '\0' is the terminator, read -d $'\0' is essentially equivalent to read -d ''. This is why I believed read did not accept null-delimited strings. However, it turns out that BASH actually handles this correctly.

I checked BASH’s souce code and found the delimiter was simply determined by delim = *list_optarg; (bash-3.2/builtins/read.def, line 296) where list_optarg points to the argument following -d. Therefore, it makes no difference to the value of delim whether $'\0' or '' is used.

Jumbled Characters after Catting a Binary File

When this happens, simply press Ctrl-V Ctrl-O Ctrl-M. Or alternatively, type "reset" and Return (Enter).

A terminal interpretes 0x0e byte as "activates the G1 character set", and 0x0f as "activates the G0 character set". The characters we read are in the G0 set. So, if there is no byte 0x0f after the last 0x0e in a binary file, everything will be shown in the unreadable G1 set, including the next shell prompt.

How does Ctrl-V Ctrl-O Ctrl-M work?
Ctrl-V is an 'escape character' - the next keystroke will always be interpreted as a literal character; Ctrl-O is 0x0f; Ctrl-M is carriage return. So the shell gets the command "\x0f" and outputs the error message "bash: \x0f: command not found". The byte 0x0f in this message turns the active character back to the readable G0.

G1 character set is not often used these days. Konsole chooses not to implement it at all, so we never have this problem in Konsole.

Department Computers

The department computer and network administrators are completely of the opposite kind of people from me. They installed everything I dislike, and almost nothing I like...
  • I dislike Ubuntu, but most of the so-called “Unix” machines are Ubuntu. (The rest are Solaris.)
  • I like bash (as most Unix-like users do these days, I bet...), but their default shell is tcsh. Perhaps this is a convention inherited from antediluvian days.
  • They have GNOME, Xfce, fvwm, Sawfish and Fluxbox installed. The only major DE/WM missing is KDE, which is my favorite.

The first time I tried to print something, it was sent to a printer in a lab 50 yards away, despite the fact that there was one only 2 yards from me. I needed to set the PRINTER environment variable so that lpr knew I wanted to use the printer in my office.

If I were using KDE, I would have finished this in 20 seconds, by catting a 2-line file to ~/.kde/env. But it took me 20 minutes to find its counterpart in GNOME, and then another 5 minutes to find out whether I should write the script ~/.gnomerc in Bourne Shell grammar or C Shell grammar. The answer is Bourne Shell grammar. Though the default shell is tcsh, ~/.gnomerc is always interpreted by /bin/sh, which is a symlink to dash (not bash) in Ubuntu and latest version of Debian... Humph.....