0

当我运行这个脚本时:

#!/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'

我试过有没有其他的,但我似乎找不到问题。谢谢

4

5 回答 5

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

发生了什么变化?更多引用(当文件名包含空格时,您的脚本迟早会中断)并使用 of[[...]]而不是 deprecated 和不太健壮(在 bash 中)[...]。我还使用read了该-r选项(因为不允许反斜杠转义任何字符)。我也改了

for svr in `cat ~/srv.lst`; do

进入更成熟的

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

(像你做的那样循环 a真的被认为是非常cat糟糕的 bash 做法)。我必须包括一个守卫[[ -n "$srv" ]]来忽略空行。如果要处理评论,您可以在此处添加更复杂的内容...

我还添加--scp,以防文件$locfile以连字符开头。那会令人困惑scp(它会认为这是一种选择)。这被认为是非常好的 shell 实践。

正如您提到的生产环境,我想我会这样做。(我经常害怕看到生产中使用的脚本)。

实际上,您的问题是关于[...]这里不需要的,因为您可以安全地将其包含在caseas 中:

#!/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 程序吗?)。相反,您应该考虑在脚本中使用参数(练习留给读者)。

$locfile通过测试是否是 dir ,您可以完全摆脱 dir vs file 的事情。并通过使用(verbose) 选项摆脱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

(因为她将能够使用制表符完成文件名),而不是调用您的脚本。

希望这可以帮助!

于 2012-12-24T14:33:26.607 回答
3

代替:

if [-n $answer] then

在“[”之后和“]”之前使用空格。如果您想在同一行中使用 'then',请使用;

if [ -n $answer ]; then

或者:

if [ -n "$answer" ]
then
于 2012-12-25T08:23:50.180 回答
2

代替

if [-n $answer] then

尝试

if [ -n $answer ]
then

也就是说,在括号中使用空格,并将 放在then不同的行上。

于 2012-12-24T13:58:09.637 回答
1

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

if [ -n $answer ]; then

就像cat-n fileecho-e foo无效。

$ which [
/usr/bin/[
于 2012-12-24T13:58:17.577 回答
1

除此之外,请始终在 中引用您的 shell 变量test -n,因此请if [ -n "$answer" ]; then改用。

于 2012-12-24T14:01:07.407 回答