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.

  • Do any of your file or directory names contain the newline character?
    – meuh
    Sep 18 '18 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 '18 at 13:18

%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:


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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.