[英]Run multiple commands in shell script using `find` and `xargs`
我试图在之后直接echo
显文件名,然后是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
它会做你期望的。 该标志用于空字节分隔的输入,而您传递的是换行分隔的输入。
要在整个管道中使用以空字节分隔的记录,请使用find ... -print0
、 sort -z
和xargs -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_HOST
、 SQL_USER
和SQL_PWD
所有扩展由子 shell执行,而不是尝试在父级中执行(请注意,这确实需要将这些值导出到环境中,而不仅仅是设置作为进程本地shell变量)。 此更改意味着可能包含对 shell 有意义的字符的 SQL 密码不会冒被解析为语法的风险。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.