在我的 bash 脚本中,我使用 find 通过通配符获取文件夹名称:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
stuff=doStuff ${i}
done
doStuff() {
echo ${1}
return ${1}'/hello';
}
问题是,当我这样做时,我收到以下错误(假设 ${i} 对应于“home/me/my_directory”):
line 111: '/home/me/my_directory': is a directory.
(第 111 行是带有“doStuff”的行)
我尝试这样做,但无济于事:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
stuff=doStuff "${i}"
done
显然这是因为程序正在尝试执行该目录,但我只想将其作为我可以操作的字符串。
答案1
引号和命令替换是您的问题。
您遇到的具体问题是因为 shell 正在尝试运行/home/me/my_directory
使用环境变量调用的命令stuff=doStuff
。
你真正想要的(如果我解释正确的话)是以doStuff
的值$i
作为参数运行,将输出分配给变量stuff
。执行此操作的方法是将命令包装在$()
.例如:
stuff="$(doStuff "$i")"
请注意我如何在所有内容周围加上引号。这是为了防止 shell 对您不希望它进行分词的内容进行分词(它将/foo/bar baz
把的单个参数变成/foo/bar
and baz
)。
此外,函数的输出被用作返回值,而不是return
.
由于您应该使用更多引号,因此您还应该将它们添加到其他所有内容中。这是脚本的完整版本:
doStuff() {
echo "${1}" >&2
printf '%s/hello' "$1";
}
IFS=$'\n'
for i in $(find "${directory}" -mindepth 1 -type d -name "${wildcard}");
do
stuff="$(doStuff "${i}")"
done
在尝试使用函数之前,您必须先放置函数定义。 Shell 不像编译程序那样进行解析,后者会多次遍历文件。这是自上而下的。
我还进行了修改,doStuff
将其发送echo
到 STDERR,它将显示在终端上,然后将其printf
发送到 STDOUT,并将其捕获到变量中stuff
。
请注意,如果您的任何目录包含换行符,这仍然会出现问题。然而,这是 shell 的限制。文件路径唯一不能包含的字符是 NULL 字符 ( \0
)。然而 bash 和其他 shell 不能在字符串中存储 NULL 字符(不是全部,但很多。我知道 zsh 可以),所以你不能将它用作分隔符。
答案2
这是一项很好的努力,但它表明您正在尝试bash
像编程语言一样进行编写,而实际上它是一种简单的脚本语言。你的构造的问题stuff=doStuff arg
在于,bash
它并不意味着你认为它意味着什么。 To bash
,stuff=doStuff
是变量赋值,并且arg
是命令。我建议您阅读以下两个链接:
与您所拥有的类似的工作版本将是
doStuff () {
echo "$1/hello"
}
stuff=$(doStuff "$i")
答案3
给出错误的行并没有按照您的想法进行操作:
它首先将环境变量 stuff 设置为字符串“doStuff”,然后尝试将 ${i} 作为命令执行。由于 ${i} 是一个目录,因此失败并显示给定的错误消息。