当我运行此脚本时:
#!/bin/bash
#This script distributes file/folders to all POP servers within the production environment.
echo "Are you willing to transfer a file or a directory? [Answer: file/dir]"
read answer
echo "Please enter a file name or a full path to the files/directories you want to distribute"
read locfile
echo "Please enter the destination path"
read destfile
if [-n $answer] then
case "$answer" in
file)
for srv in `cat ~/srv.lst`;
do echo "$srv:";
/usr/bin/scp $locfile $srv:$destfile;
done
;;
dir)
for srv in `cat ~/srv.lst`;
do echo "$srv:";
/usr/bin/scp -r $locfile $srv:$destfile;
done
;;
*)
echo "Please check your input"
esac
fi
我得到了这个输出:
./distribute_files: line 26: syntax error near unexpected token `fi'
./distribute_files: line 26: `fi'
我尝试过或不尝试其他但我似乎无法找到问题。 感谢
答案 0 :(得分:3)
我使用bash惯用语重写了你的脚本:
#!/bin/bash
#This script distributes file/folders to all POP servers within the production environment.
echo "Are you willing to transfer a file or a directory? [Answer: file/dir]"
read -r answer
echo "Please enter a file name or a full path to the files/directories you want to distribute"
read -r locfile
echo "Please enter the destination path"
read -r destfile
if [[ -n "$answer" ]] then
case "$answer" in
file)
while read -r srv; do
[[ -n "$srv" ]] || continue
echo "$srv:"
/usr/bin/scp -- "$locfile" "$srv:$destfile"
done < ~/srv.lst
;;
dir)
while read -r srv; do
[[ -n "$srv" ]] || continue
echo "$srv:"
/usr/bin/scp -r -- "$locfile" "$srv:$destfile"
done < ~/srv.lst
;;
*)
echo "Please check your input"
;;
esac
fi
发生了什么变化?更多的引用(当文件名包含空格时,您的脚本迟早会崩溃)并使用[[...]]
而不是弃用且不太健壮(在bash中)[...]
。我还使用read
和-r
选项(因为不允许反斜杠转义任何字符)。我也改变了
for svr in `cat ~/srv.lst`; do
进入更成熟的
while read -r srv; do
...
done < ~/src.lst
(它真的被认为是非常糟糕的bash练习,就像你一样循环cat
。我不得不包括一个警卫[[ -n "$srv" ]]
来忽略空行。如果想要处理评论,你可以在这里添加更复杂的东西......
我还将--
添加到scp
,以防文件$locfile
以连字符开头。这会让scp
感到困惑(它会认为这是一种选择)。这被认为是非常好的贝壳练习。
当我提到生产环境时,我想我会这样做。 (我经常害怕看到生产中使用的脚本)。
事实上,您的问题是关于此处不需要的[...]
,因为您可以安全地将其包含在case
中:
#!/bin/bash
#This script distributes file/folders to all POP servers within the production environment.
echo "Are you willing to transfer a file or a directory? [Answer: file/dir]"
read -r answer
echo "Please enter a file name or a full path to the files/directories you want to distribute"
read -r locfile
echo "Please enter the destination path"
read -r destfile
case "$answer" in
"")
true
# Do whatever you like here
;;
file)
while read -r srv; do
[[ -n "$srv" ]] || continue
echo "$srv:"
/usr/bin/scp -- "$locfile" "$srv:$destfile"
done < ~/srv.lst
;;
dir)
while read -r srv; do
[[ -n "$srv" ]] || continue
echo "$srv:"
/usr/bin/scp -r -- "$locfile" "$srv:$destfile"
done < ~/srv.lst
;;
*)
echo "Please check your input"
;;
esac
此外,像你这样的“交互式”脚本被认为是不好的做法(这让人联想到旧家庭计算机上的旧BASIC程序吗?)。您应该考虑使用脚本的参数(练习留给读者)。
你可以完全摆脱dir v.s.文件,通过测试$locfile
是否为dir。并使用echo
(详细)选项摆脱scp
告诉-v
哪个文件:
#!/bin/bash
#This script distributes file/folders to all POP servers within the production environment.
read -r -p "Please enter a file name or a full path to the files/directories you want to distribute" locfile
read -r -p "Please enter the destination path" destfile
ropt=""
if [[ -d "$locfile" ]]; then
ropt='r'
fi
while read -r srv; do
[[ -n "$srv" ]] && /usr/bin/scp -v$ropt -- "$locfile" "$srv:$destfile"
done < ~/srv.lst
事实上,我越看看你的脚本做什么,我认为用户输入终端的速度就越快:
$ while read -r srv; do [[ -n "$srv" ]] && /usr/bin/scp -v "myfile" "$srv:mydestfile"; done < ~/srv.lst
(因为她可以使用标签使用文件名完成),而不是调用你的脚本。
希望这有帮助!
答案 1 :(得分:3)
而不是:
if [-n $answer] then
在&#39; [&#39;之前&#39;]&#39;。如果你想使用&#39;那么&#39;在同一行中使用;
:
if [ -n $answer ]; then
或者:
if [ -n "$answer" ]
then
答案 2 :(得分:2)
而不是
if [-n $answer] then
试
if [ -n $answer ]
then
也就是说,在括号中使用空格,并将then
放在不同的行上。
答案 3 :(得分:1)
[
是一个命令,所以你需要尊重空白:
if [ -n $answer ]; then
就像cat-n file
或echo-e foo
无效一样。
$ which [
/usr/bin/[
答案 4 :(得分:1)
除此之外,请始终在test -n
中引用您的shell变量,因此请改用if [ -n "$answer" ]; then
。