You could do this with the xargs
command. If I have these files:
$ ls
A_file.txt B_file.txt C_file.txt D_file.txt E_file.txt F_file.txt G_file.txt H_file.txt
Then I can process these two at a time like this:
$ find . -type f | xargs -n2 echo some_program
some_program ./A_file.txt ./B_file.txt
some_program ./C_file.txt ./D_file.txt
some_program ./E_file.txt ./F_file.txt
some_program ./G_file.txt ./H_file.txt
Here I'm simply calling echo
, but you could of course drop the echo
and actually run some_program
instead. This will process two files at a time...but it doesn't handle generating an output filename for each invocation.
If we make it a little more elaborate, we can output to a file named after the first input filename:
find . -type f | xargs -n2 sh -c 'echo some_program $1 $2 > $1.output' --
This will produce the file A_file.txt.output
for A_file.txt
and B_file.txt
, C_File.txt.output
for the next pair, and so forth. You can get fancier with the output filename by applying various transformations; for example, to get the filename you asked for in your question, you could write:
find . -type f | xargs -n2 sh -c 'echo some_program $1 $2 > output_${1:2:1}${2:2:1}' --
This will generate output filenames output_AB
, output_CD
, etc.
-n2
I'd use-L2
. Also infind
I used-print0
and inxargs
I used-0
too. That to avoid problems in files with spaces (although I do not think the user has any file with spaces) – Edgar Magallon Dec 14 '22 at 04:45-print0/-0
in order to simplify the example, but I agree that in practice it's a good idea. – larsks Dec 14 '22 at 05:00find
search to the current directory and files matching the pattern?_file.txt
(if you're picking the 1st character from the names to create the name of the output file). If you don't you will pick up old output files if you run it a second time, as well as any file in any subdirectory. – Kusalananda Dec 14 '22 at 07:25$IFS
and glob characters would also be a problem. – Stéphane Chazelas Dec 14 '22 at 08:38${var:offset:pattern}
is a ksh93 operator (now also supported by bash and zsh), not a sh operator. Also, here, you're getting the 3 character of the full path, so of the first directory component in a file like./foo/bar/file.txt
not of the file name. – Stéphane Chazelas Dec 14 '22 at 08:40find
is not sorted, so it's unspecified what pairs will be passed tosome_program
. – Stéphane Chazelas Dec 14 '22 at 08:41-0/-print0
but I had no idea that this is useful for other cases apart from the simple spaces. – Edgar Magallon Dec 14 '22 at 19:09find
in the correct order somehow. – Kusalananda Dec 14 '22 at 20:16find
(e.g., do you care about upper/lower case? Numerical sort, etc?). Example:find . -name "foo*.txt" -print0 | xargs -0 printf '%s\n' | sort -f | xargs -L 2 sh -c 'echo 0=${0}, 1=${1}'
– michael Dec 14 '22 at 22:49find
finds files is dependent on the filesystem. Why are you using-print0
in your code when you then later do not use that nul terminator withsort
? – Kusalananda Dec 15 '22 at 10:37find
are going to be "environment dependent", e.g., wildcards are expanded based on LC_COLLATE as well (of coursesort
is also affected by this). E.g., trytouch a1.txt A2.txt; LC_COLLATE=en_US.UTF-8 bash -c 'echo *'; LC_COLLATE=C bash -c 'echo *'
(output:a1.txt A2.txt
andA2.txt a1.txt
). – michael Dec 16 '22 at 16:30xargs
andfind
w/print0
, my firstfind
usesprint0
, which is paired with the firstxargs -0
, but that explicitly and necessarily converts back to lines of text for input tosort
. Unfortunately, after experimenting, there's really no good one-liner piped solution here for filenames that have e.g. newlines (\n
) in them, so I'm not sure it's all worth the effort. – michael Dec 16 '22 at 16:31$0
and$1
withxargs -L 2 ...
, not$1
,$2
... on both platforms – michael Dec 16 '22 at 16:33