我正在尝试编写一个bash脚本,该脚本包含一个目录,读取目录中的每个文件,然后将该目录中每个文件的第一行追加到一个新文件中。当我在脚本中对变量进行硬编码时,它可以正常工作。
此作品:
#!/bin/bash
rm /local/SomePath/multigene.firstline.btab
touch /local/SomePath/multigene.firstline.btab
btabdir=/local/SomePath/test/*
outfile=/local/SomePath/multigene.firstline.btab
for f in $btabdir
do
head -1 $f >> $outfile
done
这不起作用:
#!/bin/bash
while getopts ":d:o:" opt; do
case ${opt} in
d) btabdir=$OPTARG;;
o) outfile=$OPTARG;;
esac
done
rm $outfile
touch $outfile
for f in $btabdir
do
head -1 $f >> $outfile
done
这是我叫脚本的方式:
bash /local/SomePath/Scripts/btab.besthits.wBp-q_wBm-r.sh -d /local/SomePath/test/* -o /local/SomePath/out.test/multigene.firstline.btab
这是我运行它时得到的:
rm: missing operand
Try 'rm --help' for more information.
touch: missing file operand
Try 'touch --help' for more information.
/local/SomePath/Scripts/btab.besthits.wBp-q_wBm-r.sh: line 23: $outfile: ambiguous redirect
有什么建议吗?我希望能够使用getopts,以便使脚本更通用。谢谢!
编写bash脚本时,您必须格外注意quoting和globbing。
当您使用全域调用脚本(此处为*
)时,它会被shell扩展并分解为单词。这是在脚本执行之前发生的。
[例如,如果您执行cat *.txt
cat将获取目录中的所有.txt文件作为其参数。它将与调用cat afile.txt nextfile.txt
(依此类推)相同。猫将永远不会看到星号。
在您的脚本中,这意味着输入-d /local/SomePath/test/*
被展开,例如/local/SomePath/test/someFile /local/SomePath/test/someOtherFile /test/someThirdFile
。随后,getopts
仅取-d
之后的第一个文件作为$btabdir
,并且在大小写切换中不处理-o
。
我建议您首先引用每个变量,最好使用"${name}"
样式,并且仅使用带引号的输入来调用脚本。也可以在目录路径中发送它,测试它是否是目录(test -d
),然后将for循环更改为for f in "${btabdir}"/*