2

I'm trying to understand why I cannot use sed in the following example.

I'm having a nested folder structure where all folders contain a text file called PKGBUILD. I want to only print out the relative path of the files containing a certain pattern, e.g., pkgname=.*dbus

If I use find in conjunction with grep I get the expected output, i.e.,

find . -name 'PKGBUILD' -exec grep -q 'pkgname=.*dbus' {} \; -print

I correctly get

./packages/dbus-python/repos/extra-x86_64/PKGBUILD
./packages/dbus-python/trunk/PKGBUILD
./packages/dbus-glib/repos/extra-x86_64/PKGBUILD
./packages/dbus-glib/trunk/PKGBUILD

as output of the relative filepath, since only those PKGBUILD files contain the correct pattern. As far as I understand the -q option in grep is responsible for omitting the print as long as there is no match found.

However I should be able to emulate the same behavior by using sed. I use it in the following way

find . -name 'PKGBUILD' -exec sed -n '/pkgname.*dbus/q' {} \; -print

where -n is used to omit output and q to quit immediately when the match is found. However, this command outputs every PKGBUILD file in the tree, regardless if sed matches anything. Why is the behavior of grep and sed here so different and how would I make the sed command work?

7
  • 1
    find uses the exit status of the -exec command to decide whether to continue with the -print. grep status depends on whether any matches occurred, but sed status does not. Dec 29, 2022 at 0:20
  • I used GNU sed and in the man page it states, that you can adjust the exit-code of sed. E.g. using sed -n '/pkgname.*dbus/q0. However the result is the same. Does sed print any invisible output to stdout? grep -q explicitly states that nothing is printed to stdout until a match is found.
    – Invarianz
    Dec 29, 2022 at 0:28
  • @don_crissti the grep solution works fine. This is a conceptual question challenging my understanding of the two programs.
    – Invarianz
    Dec 29, 2022 at 0:29
  • 2
    @Invarianz using q0 doesn't really help since 0 is the default exit status - you'd need to set a non-zero exit status on non-match. I haven't really thought it through but perhaps sed -n -e '/pkgname.*dbus/q' -e '$q1' ? Dec 29, 2022 at 0:33
  • @steeldriver that makes a lot of sense. However, the suggested command does not work and still prints everything. I guess to make the logic work I'd need to return 1 on non-match as you suggested. I would happily accept the answer if it works!
    – Invarianz
    Dec 29, 2022 at 0:38

1 Answer 1

1

As all commenters have already mentioned there is a significant difference between the return status between pattern matching via sed or via grep.

Whereas grep -q only returns a 0 status on a found match sed always returns 0 regardless if a match is found or not (There are cases where a file or stream can not be read and it actually does not give 0). Via the sed GNU extension this return status can be modified, i.e. we can change it such that sed only returns 1 when a pattern match occurs.

sed -n '/pkgname.*dbus/q1'

However the find program only prints on a return status of 0 of the previous exec action, i.e., we need to negate seds return status using !.

The full find command using sed then reads,

find . -name 'PKGBUILD' ! -exec sed -n '/pkgname.*dbus/q1' {} \; -print

with the output

./packages/dbus-python/repos/extra-x86_64/PKGBUILD
./packages/dbus-python/trunk/PKGBUILD
./packages/dbus-glib/repos/extra-x86_64/PKGBUILD
./packages/dbus-glib/trunk/PKGBUILD

as expected. Thanks to @Paul_Pedant, @steeldriver and especially @don_crissti for the great insight!

3
  • 1
    Good! Note that in practice it's better to use q7 or something above 4 (which are exit codes already used by gnu sed for specific errors...) Dec 29, 2022 at 1:06
  • 1
    This isn't quite the same as the grep version though I think? In particular, it will print the names of files for which sed exits with non-zero status for any reason - try it with a (non-matching) file for which you don't have read permission for example. Dec 29, 2022 at 1:33
  • This is true @steeldriver . I was hoping that my mention of non-zero exit codes in case of an unreadable file or stream would be enough to highlight that the print in the find command would be triggered by sed in those cases also. This does not happen with grep
    – Invarianz
    Dec 29, 2022 at 1:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .