繁体   English   中英

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

[英]Run multiple commands in shell script using `find` and `xargs`

我试图在之后直接echo显文件名,然后是sqlcmd ,但是我根本无法弄清楚如何以有效的方式连接语句。

我试过了:

  • 创建一个新函数(在 shell 中显然不能像这样在 bash 中完成)
  • 用分号分隔(转义和不转义)
  • 按照这个例子使用双&&

请任何提示。

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它会做你期望的。 该标志用于空字节分隔的输入,而您传递的是换行分隔的输入。

要在整个管道中使用以空字节分隔的记录,请使用find ... -print0sort -zxargs -0 这是通过管道传递记录的最强大的方式(无论您的文件名是什么,它都不会中断)。

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

这假设$SQL变量已export到环境中。

我已将-I %替换为-n1 ,它将一次处理一条记录。 每个文件名作为$0传递给sh ,可以安全使用; 记录的内容没有被解释为 shell 语法的风险,就像您尝试使用-I %的情况一样。 请注意,这意味着为每个文件调用一个单独的子 shell,并且像Charles 的 answer一样使用循环会更有效。

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

旨在结合安全性和性能(每个适合命令行的 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参数。 我们不使用印记,而是让 xargs 将尽可能多的项目连接到sh的参数列表的末尾。
  • sh命令中, for arg do默认在"$@"循环; 因此,它依次将$1$2等分配给名为arg的变量,这样sh一个副本就可以处理多个 SQL 文件。
  • 我们让SQL_HOSTSQL_USERSQL_PWD所有扩展由子 shell执行,而不是尝试在父级中执行(请注意,这确实需要将这些值导出到环境中,而不仅仅是设置作为进程本地shell变量)。 此更改意味着可能包含对 shell 有意义的字符的 SQL 密码不会冒被解析为语法的风险。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM