[Slackbuilds-users] [template] find .. strip doesn't work with whitespaces and '

Arkadiusz Drabczyk arkadiusz at drabczyk.org
Mon Jul 30 14:34:57 UTC 2018


Probably not the most important issue but it piqued my interest today.
Example list of files:

$ ls -1
'l'ibsuper.so
'libsuper.so
lib super.so
libsuper.so

Using find ... strip line from the current template:

$ find . -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
   | cut -f 1 -d : | xargs stat --format=%n || true
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
./libsuper.so
./libsuper.so

I noticed that this issue was first attempted to be fixed in fdf8673:

$ find . -print | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
   | cut -f 1 -d : | xargs stat --format=%n || true

It didn't work of course because -print0 was not used and fix was
provided in commit 9fb8a16 which is also what we use today.

Current approach not only fails with filenames that contain ' but also
with filenames that contain whitespaces:

$ ls -1
lib super.so
libsuper.so
$ find . -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \
   | cut -f 1 -d : | xargs stat --format=%n || true
./libsuper.so
stat: cannot stat './lib': No such file or directory
stat: cannot stat 'super.so': No such file or directory

As crazy as it seems for someone to include whitespace or ' in library
name I checked that gcc and ld.so don't have problems with that and as
fix was added to the repository I guess someone had to already
encounter this problem.

IMO the problem with the current approach is that list of files is not
passed correctly to the second xargs after cut.  A suggested fix would
be:

$ find . -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF | cut -d : -f1 | tr '\n' '\0' | xargs -0 stat --format=%n || true

or:

$ find . -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF | cut -d : -f1 | xargs -d '\n' stat --format=%n || true

There are 2 problems with that - first, it looks strange and second,
it doesn't work correctly with filenames that contain newlines.
Arguably, newlines in filenames are even less common that whitespaces
and single quotes.  Alternative fix that also works with newlines:

$ find . -print0 |  while read  -rd $'\0' x; do file "$x" | grep -e "executable" -e "shared" | grep ELF >/dev/null && stat --format=%n "$x"; done

Its disadvantage is that it's much slower than the first fix:

$ time find . -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF | cut -d : -f1 | xargs -d '\n' stat --format=%n || true
./libsuper.so
./'libsuper.so
./lib super.so
./'l'ibsuper.so

real    0m0.019s
user    0m0.034s
sys     0m0.011s
$ time find . -print0 |  while read  -rd $'\0' x; do file "$x" | grep -e "executable" -e "shared" | grep ELF >/dev/null && stat --format=%n "$x"; done./libsuper.so
./libsuper.so
./'libsuper.so
./lib super.so
./'l'ibsuper.so

real    0m0.073s
user    0m0.094s
sys     0m0.034s

-- 
Arkadiusz Drabczyk <arkadiusz at drabczyk.org>


More information about the SlackBuilds-users mailing list