Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Command 'strings' reading (not) standard input

3 views
Skip to first unread message

Janis Papanagnou

unread,
Aug 9, 2022, 2:25:56 PM8/9/22
to
Thanks to process substitution in newer shells I can write, e.g.,
strings <( zcat file.gz ) | ...

I am wondering, though, whether there's a reason why 'strings' is
not defined to support (additionally) filter calling semantics
...(binary stream)... | strings | ...(text stream)...

Janis

Lew Pitcher

unread,
Aug 9, 2022, 2:33:30 PM8/9/22
to
Closed, cannot reproduce

14:32 $ strings <(zcat ./cat.gz) | grep comment
.comment




--
Lew Pitcher
"In Skills, We Trust"

Lew Pitcher

unread,
Aug 9, 2022, 2:41:44 PM8/9/22
to
This under
GNU bash, version 4.3.48(1)-release (x86_64-slackware-linux-gnu)

Neither strings nor zcat are bash builtins (at least, not in this version)

strings resolves to /usr/bin/strings, which is "ELF 64-bit LSB executable, x86-64"

zcat resolves to /usr/bin/zcat, which is a symbolic link to /bin/zcat
/bin/zcat is a bash script that invokes gzip with the -cd option

gzip resolves to /usr/bin/gzip, which is a symbolic link to /bin/gzip
/bin/gzip is "ELF 64-bit LSB executable, x86-64"
gzip -V reports "gzip 1.12"

So, no shell trickery here, although I cannot give you the version of
strings that this works with.

Perhaps you have a different version of strings(1) than I do, or a different
version of bash(1)

HTH

Keith Thompson

unread,
Aug 9, 2022, 4:01:25 PM8/9/22
to
The reported problem is that the strings command does not read from its
standard input. The command you tried is the one that Janis said
works. `<(zcat ./cat.gz)` will expand to something like "/dev/fd/63",
which is passed as a file name argument.

But on my system, the strings command will read from stdin, though the
synopsis on the man page doesn't directly say so:

SYNOPSIS
strings [-afovV] [-min-len]
[SNIP]
[--help] [--version] file...

Using "file..." rather than "[file]..." implies that there must be at
least one file name argument, but that appears to be inaccurate:

$ echo hello | strings
hello
$

The DESCRIPTION section does talk about strings reading from stdin (and
changing behavior)

The strings command I'm using is part of GNU binutils 2.34. Perhaps
other implementations behave differently.

The strings command can be configured either to display all printable
sequences in a file or to display only those sequences that are
in loadable, initialized data sections. The latter might be more
difficult when reading from stdin rather than from a seekable file.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

Kaz Kylheku

unread,
Aug 9, 2022, 4:16:04 PM8/9/22
to
Think that it's not there because POSIX doesn't require it, I checked
POSIX. In POSIX, I found this:

"If the first argument is '-', the results are unspecified."

Aha, so implementations of strings are permitted (encouraged, I might
say) to support standard in reading via the - convention.

The wording probably exists because some strings implementations
do and some do not?

The strings from GNU Bintutils 2.30 does handle stdin---and does not
like the - argument; go figure.

Deliberate use of cat;

$ cat /proc/self/environ | strings | head -4
CLUTTER_IM_MODULE=xim
XDG_MENU_PREFIX=gnome-
LANG=en_CA.UTF-8
DISPLAY=:1

What "strings" are you looking at? Maybe it handles - as a way of
specifying stdin. (Still, if you want that in a portable
script, PITA).

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Christian Weisgerber

unread,
Aug 9, 2022, 6:30:09 PM8/9/22
to
On 2022-08-09, Janis Papanagnou <janis_pa...@hotmail.com> wrote:

There may have been an underlying rationale that executable format
parsing involves seeking rather than a linear read through the file.

For some historical perspective, I just looked at the 4.4BSD
strings(1) command: It tries to read the executable header and then
seek to the start of the text segment and only read the text and
data segments, although if it encounters an early error, it falls
back to simply reading everything.

--
Christian "naddy" Weisgerber na...@mips.inka.de

Kaz Kylheku

unread,
Aug 9, 2022, 7:53:01 PM8/9/22
to
On 2022-08-09, Christian Weisgerber <na...@mips.inka.de> wrote:
> On 2022-08-09, Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>
>> Thanks to process substitution in newer shells I can write, e.g.,
>> strings <( zcat file.gz ) | ...
>>
>> I am wondering, though, whether there's a reason why 'strings' is
>> not defined to support (additionally) filter calling semantics
>> ...(binary stream)... | strings | ...(text stream)...
>
> There may have been an underlying rationale that executable format
> parsing involves seeking rather than a linear read through the file.

POSIX specifies -a which tells strings to scan the file in its entirety.
Otherwise what part of a file is scanned is implementation-defined.

GNU binutils strings makes that the default, probably because that's the
behavior you almost always want.

strings isn't just used for executables, but anything. Firmware flash
image files, PDFs, JPEGs.

Spiros Bousbouras

unread,
Aug 10, 2022, 4:27:28 AM8/10/22
to
On Tue, 9 Aug 2022 20:15:59 -0000 (UTC)
Kaz Kylheku <480-99...@kylheku.com> wrote:
> On 2022-08-09, Janis Papanagnou <janis_pa...@hotmail.com> wrote:
> > Thanks to process substitution in newer shells I can write, e.g.,
> > strings <( zcat file.gz ) | ...
> >
> > I am wondering, though, whether there's a reason why 'strings' is
> > not defined to support (additionally) filter calling semantics
> > ...(binary stream)... | strings | ...(text stream)...
>
> Think that it's not there because POSIX doesn't require it, I checked
> POSIX. In POSIX, I found this:
>
> "If the first argument is '-', the results are unspecified."
>
> Aha, so implementations of strings are permitted (encouraged, I might
> say) to support standard in reading via the - convention.

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/strings.html :

strings [-a] [-t format] [-n number] [file...]
[...]

INPUT FILES
The input files named by the utility arguments or the standard
input shall be regular files of any format.

So a file argument is optional and it explicitly says that reading
from standard input is allowed. But I'm not sure what it means for
the standard input to be a regular file.

> The wording probably exists because some strings implementations
> do and some do not?
>
> The strings from GNU Bintutils 2.30 does handle stdin---and does not
> like the - argument; go figure.

[...]

--
vlaho.ninja/prog

Janis Papanagnou

unread,
Aug 10, 2022, 5:03:17 AM8/10/22
to
Yes, that is what works, as I wrote; using the newer process
substitution shell feature that some Unix systems support.

In older or non-supporting shells and Unix versions you'd
have tried it the "standard way"...

zcat ./cat.gz | strings | grep comment

piping the results of zcat into strings.

According to the man page you have to provide a file, and a
test of '-' as a filename substitute won't work since that's
a third alternative to options -a or --all.

Janis

Janis Papanagnou

unread,
Aug 10, 2022, 5:07:07 AM8/10/22
to
On 09.08.2022 22:01, Keith Thompson wrote:
>
> But on my system, the strings command will read from stdin, though the
> synopsis on the man page doesn't directly say so:
>
> SYNOPSIS
> strings [-afovV] [-min-len]
> [SNIP]
> [--help] [--version] file...
>
> Using "file..." rather than "[file]..." implies that there must be at
> least one file name argument, but that appears to be inaccurate:
>
> $ echo hello | strings
> hello
> $
>
> The DESCRIPTION section does talk about strings reading from stdin (and
> changing behavior)

I focused on the syntax and the option description and missed that.
It works for me as well. - Thanks!

Janis

Janis Papanagnou

unread,
Aug 10, 2022, 5:09:52 AM8/10/22
to
On 10.08.2022 10:27, Spiros Bousbouras wrote:
>
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/strings.html :
>
> strings [-a] [-t format] [-n number] [file...]

I was fooled by my man page; the POSIX syntax is clear here.

Janis

Geoff Clare

unread,
Aug 10, 2022, 8:41:07 AM8/10/22
to
Kaz Kylheku wrote:

> On 2022-08-09, Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>>
>> I am wondering, though, whether there's a reason why 'strings' is
>> not defined to support (additionally) filter calling semantics
>> ...(binary stream)... | strings | ...(text stream)...
>
> Think that it's not there because POSIX doesn't require it, I checked
> POSIX. In POSIX, I found this:
>
> "If the first argument is '-', the results are unspecified."
>
> Aha, so implementations of strings are permitted (encouraged, I might
> say) to support standard in reading via the - convention.

That text is there because with some versions of strings, "strings -"
means the same as "strings -a".

If you give an operand of '-' that isn't the first argument, e.g.
"strings -- -", then POSIX actually requires it to read from a
file named '-'. However, this doesn't match existing practice so
it is probably an oversight in POSIX (my guess, as a result of the
"first argument is '-'" text being there).

Anyway, the text most relevant to Janis's question is in the OPERANDS
section:

The following operand shall be supported:

file
A pathname of a regular file to be used as input. If no file
operand is specified, the strings utility shall read from the
standard input.

--
Geoff Clare <net...@gclare.org.uk>

Christian Weisgerber

unread,
Aug 10, 2022, 10:40:09 AM8/10/22
to
On 2022-08-10, Geoff Clare <ge...@clare.See-My-Signature.invalid> wrote:

> file
> A pathname of a regular file to be used as input. If no file
> operand is specified, the strings utility shall read from the
> standard input.

As indeed it has been doing since it appeared in 3.0BSD in 1980.

Christian Weisgerber

unread,
Aug 10, 2022, 10:40:09 AM8/10/22
to
On 2022-08-09, Kaz Kylheku <480-99...@kylheku.com> wrote:

> POSIX specifies -a which tells strings to scan the file in its entirety.
> Otherwise what part of a file is scanned is implementation-defined.
>
> GNU binutils strings makes that the default,

It does not. You can do what I just did and compare the respective
output.

> probably because that's the behavior you almost always want.

Running strings(1) on executables is a common usage, though. And
if the file isn't stripped, you generally don't want the strings
from the symbol table cluttering the output.

Lew Pitcher

unread,
Aug 10, 2022, 1:43:48 PM8/10/22
to
On Tue, 09 Aug 2022 13:01:18 -0700, Keith Thompson wrote:

> Lew Pitcher <lew.p...@digitalfreehold.ca> writes:
>> On Tue, 09 Aug 2022 20:25:50 +0200, Janis Papanagnou wrote:
>>
>>> Thanks to process substitution in newer shells I can write, e.g.,
>>> strings <( zcat file.gz ) | ...
>>>
>>> I am wondering, though, whether there's a reason why 'strings' is
>>> not defined to support (additionally) filter calling semantics
>>> ...(binary stream)... | strings | ...(text stream)...
>>
>> Closed, cannot reproduce
>>
>> 14:32 $ strings <(zcat ./cat.gz) | grep comment
>> .comment
>
> The reported problem is that the strings command does not read from its
> standard input. The command you tried is the one that Janis said
> works. `<(zcat ./cat.gz)` will expand to something like "/dev/fd/63",
> which is passed as a file name argument.
[snip]

Ghu! You're right. I misread Janis' post. Sorry.

But, both the "util-linux" version of strings
(https://github.com/util-linux/util-linux)
/and/ the GNU strings implementation (both part of Slackware Linux)
read their data from standard input, and write their results to
standard output.

In Slackware 14.2, the util-linux version of strings does not report
a version number, but came in the util-linux 2.27.1 implementation.
The GNU version of strings reports "GNU strings version 2.26.20160125"

I find it unusual that Janis' version of strings(1) does /not/ default
to stdin/stdout. Or, perhaps he didn't try it?

Janis Papanagnou

unread,
Aug 10, 2022, 4:00:24 PM8/10/22
to
On 10.08.2022 19:43, Lew Pitcher wrote:
>
> I find it unusual that Janis' version of strings(1) does /not/ default
> to stdin/stdout. Or, perhaps he didn't try it?

As I wrote in my other posts I got fooled by the syntax description
of my strings man page; there I saw that a file was requested and
tried just the often seen stdin/stdout as placeholder '-' (which
didn't work, though, because that has another meaning in my strings
command).

Janis

Kaz Kylheku

unread,
Aug 10, 2022, 9:40:01 PM8/10/22
to
On 2022-08-10, Christian Weisgerber <na...@mips.inka.de> wrote:
> On 2022-08-09, Kaz Kylheku <480-99...@kylheku.com> wrote:
>
>> POSIX specifies -a which tells strings to scan the file in its entirety.
>> Otherwise what part of a file is scanned is implementation-defined.
>>
>> GNU binutils strings makes that the default,
>
> It does not. You can do what I just did and compare the respective
> output.

Sorry, I should have clarified is that what what is default is the -a,
not what is described by my "Otherwise" sentence, and that I was going
by what is documented:

$ strings -h
Usage: strings [option(s)] [file(s)]
Display printable strings in [file(s)] (stdin by default)
The options are:
-a - --all Scan the entire file, not just the data section [default]

Christian Weisgerber

unread,
Aug 11, 2022, 9:30:09 AM8/11/22
to
On 2022-08-11, Kaz Kylheku <480-99...@kylheku.com> wrote:

>>> GNU binutils strings makes that the default,
>
> Sorry, I should have clarified is that what what is default is the -a,

That's what I understood and disagreed with.

> $ strings -h
> Usage: strings [option(s)] [file(s)]
> Display printable strings in [file(s)] (stdin by default)
> The options are:
> -a - --all Scan the entire file, not just the data section [default]

So that default has changed, because...

$ strings /usr/bin/make |wc
1163 2871 20472
$ strings -a /usr/bin/make |wc
1188 2896 20698
$ strings --version
GNU strings (GNU Binutils for Debian) 2.22
Copyright 2011 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.

Keith Thompson

unread,
Aug 11, 2022, 3:23:02 PM8/11/22
to
GNU binutils can be configured at build time to default either to
"-a/--all" (scan the entire file) or "-d/--data" (only scan the
data sections). Different distributions (Debian et al) might
configure it differently. The usage message changes depending
on how it's configured. (See DEFAULT_STRINGS_ALL in the binutils
sources if you're interested in the details.)

Regardless of that configuration, it will scan the entire file if
it doesn't recognize the file type or if it's reading from stdin.
0 new messages