Bash 我写了这个脚本,但似乎我遗漏了一些语法

Bash 我写了这个脚本,但似乎我遗漏了一些语法,bash,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 answer echo "Please enter a file name or a full path to

运行此脚本时:

#!/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'
我试过使用或不使用其他方法,但似乎找不到问题。 谢谢

而不是

if [-n $answer] then
试一试


也就是说,使用括号中的空格,然后将
放在另一行。

[
是一个命令,因此您需要尊重空格:

if [ -n $answer ]; then
就像
cat-n文件
echo-e-foo
无效一样

$ which [
/usr/bin/[

除此之外,请始终在
test-n
中引用shell变量,因此请使用
if[-n“$answer”];然后使用

我使用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
进入更成熟的阶段

while read -r srv; do
    ...
done < ~/src.lst

同样,像你这样的“交互式”脚本被认为是不好的练习(这让人联想到旧的家庭计算机上的老的基本程序吗?)你应该考虑使用脚本的参数(留给读者的练习)。 通过测试

$locfile
是否为dir,您可以完全删除dir v.s.文件。通过使用
-v
(verbose)选项,可以删除告诉它是哪个文件的
echo

!/bin/bash
#此脚本将文件/文件夹分发到生产环境中的所有POP服务器。
read-r-p“请输入要分发的文件/目录的文件名或完整路径”locfile
读取-r-p“请输入目标路径”文件
ropt=“”
如果[[-d“$locfile”]];则
ropt='r'
fi
读取时-r srv;执行
[[-n“$srv”]&&&/usr/bin/scp-v$ropt--“$locfile”$srv:$destfile”
完成<~/srv.lst
事实上,我越是关注您的脚本所做的事情,就越觉得用户在终端上键入内容的速度要快得多:

$ while read -r srv; do [[ -n "$srv" ]] && /usr/bin/scp -v "myfile" "$srv:mydestfile"; done < ~/srv.lst
$while read-r srv;do[[-n“$srv”]]和&/usr/bin/scp-v“myfile”“$srv:mydestfile”;完成
(因为她将能够使用带有选项卡的文件名补全),而不是调用您的脚本

希望这有帮助!

而不是:

if [-n $answer] then
在“[”之后和“]”之前使用空格。如果要在同一行中使用“then”,请使用

if [ -n $answer ]; then
或:


这就解决了问题,你能告诉我区别吗?@ItaiGanot空格是用来在bash中指定一个条件语句的。而且,
if
行必须在
then
之前终止,所以要么使用分号,要么将
then
放在一个单独的行中。这两个都只是shell中的怪癖。@ItaiGanot没有o shell中的怪癖。当您编写
if[-n$answer]then
时,bash将尝试使用参数执行命令
[-n
(扩展)
$answer
then
,这不是您想要的。相反,您想要的是
if[-n$answer];then
。但是请参阅我的答案以获得更多(好的)选项。
这是什么[
在这里不相关,因为(在bash中),
[
是一个内置的,您可以使用
类型[
快速检查。好吧,即使是内置的也是命令,不是吗?最好指出
[
不是语法糖,而是像任何其他命令或内置命令一样。首先,感谢您的反馈,非常感谢,我期待着明天在工作中更改我的脚本。其次,这一切都是从一行编写开始的,甚至不需要脚本,但目前,我的团队中没有人知道Linux和Linux这只是为了让他们在我不在的情况下更容易些。无论如何,非常感谢所有这些信息!
#!/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
if [-n $answer] then
if [ -n $answer ]; then
if [ -n "$answer" ]
then