运行 shell 脚本中的多个命令使用 `find` 和 `xargs`
Run multiple commands in shell script using `find` and `xargs`
我正在尝试 echo
文件名,然后 sqlcmd
之后直接 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
,它就会如您所愿。该标志用于 null-byte-separated 输入,而您将其传递给 newline-separated 输入。
要在整个管道中使用 null-byte-separated 条记录,请使用 find ... -print0
、sort -z
和 xargs -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_HOST
、SQL_USER
和 SQL_PWD
等值的所有扩展由 child shell 执行 ],而不是尝试在 parent 中执行它们(请注意,这 确实 要求将这些值导出到环境中,而不是仅仅设置为process-local shell 个变量)。此更改意味着 SQL 密码可能包含对 shell 有意义的字符,不会冒被解析为语法的风险。
我正在尝试 echo
文件名,然后 sqlcmd
之后直接 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
,它就会如您所愿。该标志用于 null-byte-separated 输入,而您将其传递给 newline-separated 输入。
要在整个管道中使用 null-byte-separated 条记录,请使用 find ... -print0
、sort -z
和 xargs -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_HOST
、SQL_USER
和SQL_PWD
等值的所有扩展由 child shell 执行 ],而不是尝试在 parent 中执行它们(请注意,这 确实 要求将这些值导出到环境中,而不是仅仅设置为process-local shell 个变量)。此更改意味着 SQL 密码可能包含对 shell 有意义的字符,不会冒被解析为语法的风险。