我正在尝试使用当前目录和所有子目录,并在每个以.sql结尾的文件中添加一些注释
这是一段代码
HEADER="--SQL HEADER"
for f in 'find . -name *.sql';
do
echo $f
echo -e $HEADER > $f.tmp;
FNAME=${f//\//_/};
echo -e "\n\n--MORE ANNOTATIONS ${FNAME%.*}:1" >> $f.tmp;
cat $f >> $f.tmp;
mv $f.tmp $f;
rm $f.tmp
done;
我是bash的初学者所以我认为我得到的一些错误可能是由于循环的find语句 但这是我得到的错误
find . -name X.sql A.sql W.sql E.sql S.sql
./annotate.sh: line 6: $f.tmp: ambiguous redirect
./annotate.sh: line 8: $f.tmp: ambiguous redirect
./annotate.sh: line 9: $f.tmp: ambiguous redirect
mv: invalid option -- n
Try `mv --help' for more information.
rm: invalid option -- n
Try `rm --help' for more information.
任何帮助将不胜感激=)
答案 0 :(得分:3)
这是问题所在。你的“回声”让它消失了:
echo $f
输出
find . -name X.sql A.sql W.sql E.sql S.sql
我认为问题是你在find命令中有单引号(''),而不是反引号(``)。所以它不是真正运行查找,而是简单地扩展通配符。
您可能必须引用通配符,以便将其传递给find而不是由shell评估:
for f in `find . -name \*.sql`;
但是,您的脚本中存在一些问题,如果您想多次使用它,则应该解决这些问题。请参阅ormaaj's answer。
答案 1 :(得分:2)
正如已经指出的那样,问题是查找实际上并未执行。但是,这种模式非常错误。使用for循环对命令替换发生的任何事情进行迭代都不起作用,因为将输出拆分为单词需要进行单词拆分,这需要不引用,即使禁用路径名扩展也是一个问题,因为文件名可以包含换行符。 / p>
最好使用-exec
。首先将此脚本写入文件chmod u+x scriptname
:
#!/usr/bin/env bash
header="--SQL HEADER"
for f in "$@"; do
echo "$f" >&2
fname=${f//\//_/}
cat - "$f" <<EOF >"$f.tmp"
${header}$'\n\n'
--MORE ANNOTATIONS ${fname%.*}:1
EOF
mv "$f.tmp" "$f"
done
然后像这样运行find
:
find . -name '*.sql' -exec scriptname {} +
或者,(并假设这是Bash的最新版本),使用globstar
而不是find
(如果您愿意,ksh具有类似的功能)。根据作业,这可能会更慢 - shell必须预先生成文件列表。
#!/usr/bin/env bash
shopt -s globstar
for f in ./**/*.sql; do
...
或者,如果您有Bash 4和具有必要GNU实用程序的系统,请使用-print0
。
find . -name '*.sql' -print0 | while IFS= read -rd '' f; do
# <body of the above for loop here>
done