使用 Find 列出文件并在输出中包含计数器值

Pet*_*ill 4 bash find shell-script macos

出于性能原因,我想用来find列出大量文件,但也在每行上包含一个计数器。以下是我到目前为止所拥有的:

local root_dir="."
local ouptut_file="/tmp/foo.txt"

File_Number=99              ## Initial value

echo "" > "${ouptut_file}"  ## Initialize file to empty

find "$root_dir"   \
    -type f        \
    -depth 2       \
    -name '*.xxx'  \
    -print0        \
| sort -z          \
| xargs -0  printf "DoSomething %5d '%s'\n" $[File_Number++] -- \
> "${ouptut_file}"
Run Code Online (Sandbox Code Playgroud)

这输出

DoSomething    99 '--'
DoSomething     0 'dirA/dirB/file1.xxx'
DoSomething     0 'dirA/dirB/file2.xxx'
DoSomething     0 'dirA/dirB/file3.xxx'
Run Code Online (Sandbox Code Playgroud)

我想要的是

DoSomething     100 'dirA/dirB/file1.xxx'
DoSomething     101 'dirA/dirB/file2.xxx'
DoSomething     102 'dirA/dirB/file3.xxx'
Run Code Online (Sandbox Code Playgroud)

如何包含计数器并消除输出中的第一个杂散线。

系统bash:正在macOS Ventura 13.0.1 上使用

mur*_*uru 5

一些注意事项:

  1. $[...]是一种非常古老的算术展开式。如今 bash 文档甚至没有提及它。$((...))代替使用。
  2. xargs将为该命令的每次调用启动一个新进程,因此对其中一个变量的任何更改都不会影响其他调用。
  3. 对于printf(1),--就像任何其他参数一样。发生的情况是xargs运行printf "DoSomething %5d '%s'\n" $[File_Number++] dirA/dirB/file1.xxx dirA/dirB/file2.xxx ..., 并printf循环参数以满足格式字符串要求。因此,每个备用文件名实际上都被视为一个数字,从而导致0输出。

您可能想使用类似的东西:

find "$root_dir"   \
    -type f        \
    -depth 2       \
    -name '*.xxx'  \
    -print0        \
| sort -z          \
| while read -r -d '' file; do
     printf "DoSomething %5d '%s'\n" $((File_Number++)) "$file"
  done > "${ouptut_file}"
Run Code Online (Sandbox Code Playgroud)

另请注意,如果您实际上使用它来打印在 shell 中运行的命令,则应该使用%q而不是'%s'正确引用。从help printf

除了标准 printf(1) 格式之外,%b 表示在相应参数中展开反斜杠转义序列,%q 表示以可重复用作 shell 输入的方式引用参数。