我有一个现有的 bash 脚本,我这样称呼它:
find /path/to/my/stuff -type d -exec sh -c 'cd "$0"; /path/to/my/script.sh function_name fn_parameter' {} \;
我经常更改/path/to/my/stuff
and fn_parameter
。我有时还需要更改function_name
.
不断重新输入这个命令变得很乏味,所以我想将它包装在另一个脚本中,并像这样传递这三个参数:
wrapper.sh function_name "/path/to/my/stuff" fn_parameter
旁注:我更改了参数的顺序,因为“function_name”是最不频繁更改的参数。
当我尝试制作这个包装脚本时,我被引用和转义弄得不知所措。我查看了 shellcheck.net 中的脚本,还尝试使用数组 for cmd
(请参阅下面的失败尝试之一)但没有成功。我确实理解问题很可能是引号和反斜杠没有得到尊重,但我不明白如何解决这个问题。
这是我许多失败的尝试之一:
包装器.sh
#!/bin/bash
function_name=$1
mpath="$2"
arg=$3
find "$mpath" -type d -exec sh -c "cd \"$0\"; /path/to/my/script.sh $function_name $arg" {} \;
这是失败尝试的另一个示例:
#!/bin/bash
function_name=$1
mpath="$2"
arg=$3
cmd="'cd \$0; /path/to/my/script.sh $function_name $arg'"
echo "find \"$mpath\" -type d -exec sh -c $cmd {} \;"
find "$mpath" -type d -exec sh -c $cmd {} \;
在上面的例子中,如果我在命令行输入 echo 语句的输出,它就可以正常工作。但是包装器失败了:
$0;: -c: line 1: unexpected EOF while looking for matching `''
$0;: -c: line 2: syntax error: unexpected end of file
为了完整起见,myscript.sh 与此类似:
#!/bin/bash
fn1() {
...
}
fn2() {
...
}
fn3() {
...
}
"$@"
您的代码的两个变体,每个都将特殊值传递到您从中调用的内联脚本中
find
:找到目录时,
find
只需将两个变量的值fn_name
作为目录路径参数之前的两个第一个参数传递fn_arg
到脚本中。sh -c
在脚本内部,我们使用前两个参数作为脚本的参数,第三个作为进入的目录路径cd
。注意
$0
将包含字符串sh
。shell 将在它可能产生的任何错误消息中使用这个(任意)字符串(你在你的问题中展示了一个例子)。该$0
值不是位置参数列表的一部分。另一个变体,它一次调用具有尽可能多的目录路径的内联脚本:
通过在命令末尾更改
\;
为,我们使用批量找到的目录路径调用 。然后,内联脚本必须遍历这些并依次调用您的脚本。+
find
sh -c
内联脚本首先从位置参数列表中选择函数名称和参数,然后将它们从该列表中移出。然后它循环遍历剩余的参数和调用
cd
以及每个脚本。以下是插入了一些额外空气的内联脚本:我在子 shell 中运行循环体,以避免
cd
每次运行脚本后都必须“返回”。我在
sh
这里使用,而不是bash
因为sh
运行此代码没有任何不足。此外,find
此处显示的命令仅使用标准功能。这是我提出的(和有效的)解决方案:
编辑:针对评论,此解决方案不适用于相对路径。