7

I want to use find to find some files, and return all files as a single line (without newline characters), and a custom delimiter between the files.

So for example the result for three files would be

/my/file/1::/my/file/2::/my/file/3

instead of

/my/file/1
/my/file/2
/my/file/3

Is there any way of achieving this using standard unix tools in combination with find?

2

3 Answers 3

12

With the GNU implementation of find and sed, you can use :

find . -type f -printf '%p::' | sed '$s/::$/\n/'
  • The -printf predicate of GNU find will print the file names in a single line delimited by :: and then sed will substitute the last :: on the last (here undelimited) line with a newline.

Example :

$ find . -type f -printf '%p\n'
./foo
./test file
whose name
contains newline characters and ::
./bar

$ find . -type f -printf '%p::' | sed '$s/::$/\n/'
./foo::./test file
whose name
contains newline characters and ::::./bar

The standard equivalent of -printf '%p::' would be -exec printf '%s::' {} +. There is no equivalent for that GNU sed expression as POSIX sed cannot handle non-text.

3
  • 1
    For the record: availability of the expression -printf. Other finds will output something like: find: -printf: unknown option or find: unrecognized: -printf... Jul 6, 2015 at 10:07
  • 1
    On macOS, you can install the GNU version of find using Homebrew: brew install findutils and use gfind instead of find.
    – Frederic
    Dec 21, 2018 at 9:57
  • If unfamiliar with sed, head -c-2 is easier to understand. The number specifies the number of characters not to print from the end.
    – AleXoundOS
    Dec 12, 2021 at 21:36
0

With zsh:

(){ print -r -- ${(j[::])argv}; } /my/**/*(N.)

To find all the regular non-hidden files under /my/ and print their paths (sorted lexically, though see the n, o and O qualifiers for alternative sorting orders) joined with ::.

0

You won't find -prinf in many find implementations. For those cases you can achieve the same by using the -exec command.

find "/some/dir" -exec echo -n {}"|" \;

echo prints every dir entry

The -n modifier avoids printing a new line character

The "|" character is appended after every entry

If your echo implementation does not support the -n flag, simple:

find "/some/dir" -exec printf "%s" {}"|" \;

The above will work in virtually any bash shell, including busybox which is present in minimalistic firmware oriented distros like OpenWRT or VMWare ESXi.

(*) Please, note that the printf call in the last example is external to find and not a find option as is posed in the first answer. printf as a binary is present in almost any distro you can think of, even the smallest ones.

4
  • You won't find that many echo implementations that support -n (though you'll find many that can't be used to display arbitrary file paths as they treat backslash specially) or that many find implementations that will replace {} with the current file path when it's not on its own in an argument. Jun 28, 2022 at 19:46
  • The first argument of printf is the format. You shouldn't use variable things there (that will fail if the file names contain % or backslash characters). If you use a proper format, then you can use one printf invocation for several file paths as shown in the accepted answer. Jun 30, 2022 at 11:03
  • That also had an easy fix. The accepted answer, which has been there 7 years so far, didn't take on account that many find implementations including some versions of Busybox's (some of the most used set of command line tools) lack the printf argument, thus I had to look for a workaround, which in the end turns out to be more wide compatible than the accepted answer. Not looking for a discussion on this, I'm busy, let people decide what suits their needs best.
    – Daniel J.
    Jun 30, 2022 at 16:16
  • The accepted answer has -exec printf '%s::' {} + (added after you posted your answer though) which is standard (-exec cmd {} + was first added on SysV circa 1983, specified by POSIX since 1992, but some find implementations like on some BSDs didn't support it until the mid 2000s, and it's possible stripped down find implementations still don't support it). -exec printf "%s" {}"|" \; is not standard nor portable. -exec printf "%s|" {} \; would be but runs one printf per file (less of a problem in some builds of recent busybox where that doesn't involve a fork+exec). Jun 30, 2022 at 16:23

You must log in to answer this question.

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