将大量文件传递给stdin,提取第一列,然后将它们组合到一个新文件中

Dar*_*gor 7 bash shell stdin cut paste

假设我们有这两个文件:

$ cat ABC.txt 
ABC DEF

$ cat PQR.txt 
PQR XTZ
Run Code Online (Sandbox Code Playgroud)

我们希望用每个文件的第1列形成一个文件.这可以通过以下方式实现:

$ paste -d ' ' <(cut -d ' ' -f 1 ABC.txt) <(cut -d ' ' -f 1 PQR.txt )
ABC PQR
Run Code Online (Sandbox Code Playgroud)

但是我想在输入中使用大量的文件,不仅是ABC.txt和PQR.TXT,还有很多.我们如何概括这种情况来传递集合中的每个文件以剪切然后将所有输出传递给粘贴(我知道这可以用awk做得更好,但我想知道如何使用这种方法解决这个问题).


编辑1

我发现了一种肮脏,肮脏的方式:

$ str='';  for i in *.txt; \
           do    str="${str} <(cut -d ' ' -f 1 ${i})"; \
           done ; \
  str="paste -d ' ' $str"; \
  eval $str
Run Code Online (Sandbox Code Playgroud)

但请,让我的灵魂释放一个不涉及计算机科学地狱的答案.

编辑2

如果这很重要,每个文件可以有n行.

tha*_*guy 5

进程替换<(somecommand)不会传递给stdin,它实际上会在单独的文件描述符上打开一个管道,例如63,然后传入/dev/fd/63.打开此"文件"时,内核*复制fd而不是打开真实文件.

我们可以通过打开一堆文件描述符然后将它们传递给命令来做类似的事情:

# Start subshell so all files are automatically closed
(
  fds=()
  n=0
  # Open a new fd for each process subtitution
  for file in ./*.txt
  do
    exec {fds[n++]}< <(cut -d ' ' -f 1 "$file")
  done

  # fds now contain a list of fds like 12 14
  # prepend "/dev/fd/" to all of them
  parameters=( "${fds[@]/#//dev/fd/}" )

  paste -d ' ' "${parameters[@]}"
)
Run Code Online (Sandbox Code Playgroud)

{var}< file是bash的动态文件描述符赋值语法.喜欢var=4; exec 4< file;但不必硬编码4而是让bash选择一个免费的文件描述符.exec在当前shell中打开它.

*无论如何,Linux,FreeBSD,OpenBSD和XNU/OSX.这不是POSIX,但也不是<(..)