尝试将目录名称传递给函数时出现“是目录”错误

use*_*763 6 bash find shell-script

在我的 bash 脚本中,我使用 find 通过通配符获取文件夹名称:

for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
  stuff=doStuff ${i}
done

doStuff() {
  echo ${1}
  return ${1}'/hello';
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我这样做时,我收到以下错误(假设 ${i} 对应于“home/me/my_directory”):

line 111: '/home/me/my_directory': is a directory. 
Run Code Online (Sandbox Code Playgroud)

(第 111 行是带有 'doStuff' 的行)

我试过这样做,但无济于事:

for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
  stuff=doStuff "${i}"
done
Run Code Online (Sandbox Code Playgroud)

显然这是因为程序正在尝试执行该目录,但我只是希望它作为一个我可以操作的字符串。

phe*_*mer 8

引号和命令替换是您的问题。

您遇到的具体问题是因为 shell 正在尝试运行/home/me/my_directory使用环境变量调用的命令stuff=doStuff
您真正想要的(如果我的解释正确的话)是以doStuff的值$i作为参数运行,将输出分配给变量stuff。这样做的方法是将您的命令包装在$(). 例如:

stuff="$(doStuff "$i")"
Run Code Online (Sandbox Code Playgroud)

请注意我如何在所有内容周围加上引号。这是为了防止 shell 对您不希望它进行分词的内容进行分词(它会将 的单个参数/foo/bar baz转换为/foo/barand 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
Run Code Online (Sandbox Code Playgroud)

在尝试使用它之前,您必须放置函数定义。Shell 不像编译程序那样被解析,它会多次遍历文件。它是自上而下的。
我还修改doStuff了将 发送echo到 STDERR,它将在终端上显示,然后printf发送到 STDOUT,在那里它将被捕获到变量中stuff

请注意,如果您的任何目录包含换行符,这仍然会出现问题。但是,这是外壳的限制。文件路径不能包含的唯一字符是 NULL 字符 ( \0)。但是 bash 和其他 shell 不能在字符串中存储 NULL 字符(不是全部,而是很多。我知道 zsh 可以),因此您不能将其用作分隔符。