在 bash 脚本中,我定义了一个从find
.问题是变量的范围没有扩展到函数。如何从函数中访问变量?这是一个例子:
variable="Filename:"
myfunction() {
echo $variable $1
}
export -f myfunction
find . -type f -exec bash -c 'myfunction "{}"' \;
这将输出文件名,但不包含字符串“Filename:”。
是否有更好的方法来调用函数,find
以便为找到的每个文件调用该函数find
,并且仍然定义变量?
答案1
不是你问题的答案,但可以不是做:
find . -type f -exec bash -c 'myfunction "{}"' \;
除了它不可移植这一事实之外,它还非常危险,因为文件名最终会被解释为bash
shell 代码。例如,考虑一下如果那里有一个文件被调用会发生什么$(rm -rf ~)
。写下来:
find . -type f -exec bash -c 'myfunction "$1"' find+bash {} \;
或者甚至更好(以避免bash
每个文件运行一个):
find . -type f -exec bash -c 'for file do
myfunction "$file"; done' find+bash {} +
现在就主题问题回答一下:
你可以这样做:
{ find . -type f -exec printf '%s\0' {} + | while IFS= read -ru3 -d '' file; do
myfunction "$file"; done 3<&0 <&4 4<&-; } 4<&0
这样,您就可以myfunction
在当前bash
shell 中进行调用,因此无需导出myfunction
或运行其他bash
shell。
如果你find
支持-print0
谓词(比如 GNU、busybox 和一些 BSD find
),你可以替换-exec printf '%s\0' {} +
为-print0
答案2
您可以声明variable
为环境变量,即
export variable="Filename:"
答案3
我会这样做
#!/bin/bash
myfunction() {
local var="Filename: "
local file=$1
echo "$var" "$file"
}
export -f myfunction
find . -type f -exec bash -c 'myfunction {}' \;
将变量声明为本地变量并将“{}”传递给作为第一个位置参数的函数$1
。
答案4
当您分配给一个变量时,它开始时是一个 shell 变量。为了获取传递给子进程的环境变量,您需要导出它。
variable="Filename:"
export variable
您可以将作业与export
:放在同一行export variable="Filename:"
。
该变量对于 启动的 shell 可见find
,但对函数不可见。在 bash 中,您还可以导出函数。这种可能性在 ksh、dash 和其他经常使用的 shell 中不存在,sh
因为它们更快、更精简。
export -f myfunction # bash only
切勿在(或){}
中的字符串内使用,除非您知道文件名是字母数字。如果文件名中有任何特殊字符,内壳将对其进行解析。相反,在 shell 的命令行上传递文件名。find -exec …
xargs …
find . -type f -exec bash -c 'for x; do myfunction "$x"; done' _ {} +
对于 bash 以外的 shell,在内 shell 中定义函数,或者直接放入其代码。
或者,在 bash 中,您可以使用递归通配符代替查找。请注意,bash 会遍历目录的符号链接。
variable="Filename:"
myfunction () { … }
shopt -s globstar dotglob
for x in **/*; do
if [[ -f $x ]]; then myfunction "$x"; fi
done