运行 shell 脚本中的多个命令使用 `find` 和 `xargs`

Run multiple commands in shell script using `find` and `xargs`

我正在尝试 echo 文件名,然后 sqlcmd 之后直接 sqlcmd 但是我根本不知道如何以有效的方式连接语句。

我试过:

请多多指教。

find "./src/ALs/Database/SQL" -iname "*.sql" | sort -n | xargs -0 -I % sh -c 'echo % && sqlcmd -S $SQL_HOST -d Database -U $SQL_USER -P $SQL_PWD -i %'

我认为,如果您从 xargs 中删除 -0,它就会如您所愿。该标志用于 null-byte-separated 输入,而您将其传递给 newline-separated 输入。

要在整个管道中使用 null-byte-separated 条记录,请使用 find ... -print0sort -zxargs -0。这是通过管道传递记录的最可靠方式(它不会中断,无论您的文件名是什么)。

find "./src/AdviserLinks/Database/SQL" -iname "*.sql" -print0 | 
  sort -zn | 
  xargs -0 -n1 sh -c 'echo "[=10=]" && 
    sqlcmd -S "$SQL_HOST" -d WebSupportDatabase -U "$SQL_USER" -P "$SQL_PWD" -i "[=10=]"'

这假设 $SQL 变量被 export 编辑到环境中。

我已将 -I % 替换为 -n1,这将一次处理一条记录。每个文件名作为[=20=]传给sh,可以放心使用;不存在将记录的内容解释为 shell 语法的风险,就像您尝试 -I % 的情况一样。请注意,这意味着每个文件都会调用一个单独的子 shell,并且使用 .

中的循环会更有效

至于使用单独的语句与 &&,这取决于您是否希望第二个命令的执行以第一个命令的成功为条件。

旨在兼顾安全性和性能(每个适合命令行的 sql 文件列表仅调用 sh 一次):

find "./src/AdviserLinks/Database/SQL" -iname "*.sql" -print0 | 
  sort -zn | 
  xargs -0 sh -c '
    for arg do
      echo "$arg"
      sqlcmd -S "$SQL_HOST" -d WebSupportDatabase -U "$SQL_USER" -P "$SQL_PWD" -i "$arg"
    done
  ' _ 

注:

  • 我们根本没有使用 xargs-I 参数。我们不使用 sigil,而是让 xargs 将尽可能多的项目连接到 sh.
  • 的参数列表的末尾
  • sh命令中,for arg do默认循环"$@";因此,它将 </code>、<code> 等依次赋值给名为 arg 的变量,这样 sh 的一个副本就可以处理多个 SQL 文件.
  • 我们让 SQL_HOSTSQL_USERSQL_PWD 等值的所有扩展由 child shell 执行 ],而不是尝试在 parent 中执行它们(请注意,这 确实 要求将这些值导出到环境中,而不是仅仅设置为process-local shell 个变量)。此更改意味着 SQL 密码可能包含对 shell 有意义的字符,不会冒被解析为语法的风险。