0

Specifically, in mkinitcpio the command find -mindepth 1 -printf '%P\0' is used, what would be a way to recreate a command with identical output without the -printf flag. https://git.archlinux.org/mkinitcpio.git/tree/mkinitcpio This is the full script in case it is useful.

2
  • Do any of your file or directory names contain the newline character?
    – meuh
    Sep 18, 2018 at 10:33
  • @meuh I don't know what files or directories it's finding, it's using it to find all the files to put into the initramfs. I don't see a reason the files or directories would have a newline character though.
    – E5ten
    Sep 18, 2018 at 13:18

2 Answers 2

0

%P will give the relative path of the file starting from the directory used as starting point, so that if find is run with some/path as starting point and it finds the pathname some/path/to/file, then %P will expand to to/file.

When GNU find is not given a starting point (as in the command given in the question), it will use the current directory (.) as the starting point. The %P format will therefore remove ./ from the found paths in this case.

To do the same thing as -printf '%P\0' with a non-GNU find implementations, assuming -mindepth is still available (as in find on BSD systems):

find . -mindepth 1 -exec sh -c '
    for pathname do
        printf "%s\0" "${pathname#./}"
    done' sh {} +

The embedded sh -c script will get a batch of pathnames from find to work on and uses a standard parameter expansion that removes the initial ./ from the pathname before printing it with a terminating nul-character.


The same thing, but with a variable holding the single top-level directory path:

topdir=/some/path

find "$topdir" -mindepth 1 -exec sh -c '
    topdir=${1%/}; shift
    for pathname do
        printf "%s\0" "${pathname#$topdir/}"
    done' sh "$topdir" {} +
1
  • -mindepth 1 can be written standardly with ! -name . or ! -path . Feb 9, 2023 at 8:54
0

In -printf '%P\0' the %P is just removing the initial ./ from the front of the filename. You can do the equivalent with sed 's|^\./||'. The \0 part produces a null character instead of newline between each filename. You can convert newline to null with tr '\n' '\0'. So you can try

find . -mindepth 1 -print | sed 's|^\./||' | tr '\n' '\0'

If any names contain a newline, this will corrupt them, translating that newline to null and transform file paths such as ./foo<newline>./bar to foo<null>bar.

You must log in to answer this question.

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