0

我编写了一个 bash 脚本,用于在我的家庭服务器上上传文件。它是从使用 applescript 的文件夹操作脚本中激活的。设置是我桌面上名为 place_on_server 的文件夹。它应该具有与我要写入的文件夹完全相同的内部文件结构: /var/www/media/ 用法如下所示:

  • 如果将目录等添加到 place_on_server: ./upload DIR 等
  • if directory of directory: etc/movies ./upload DIR etc movies //等等
  • if file to place_on_server: ./upload F file.txt
  • if file in file in place_on_server ./upload F etc file.txt //等等

用于创建一个目录,它应该执行如下命令:

ssh root@192.168.1.1<<EOF
cd /var/www/media/wherever
mkdir newdirectory
EOF

和文件放置:

rsync -rsh='ssh -p22' file  root@192.168.1.1:/var/www/media/wherever

脚本:

#!/bin/bash
addr=$(ifconfig -a | ./test)
if ($# -le "1")
then
    exit
elif ($1 -eq "DIR")
then
    f1="ssh -b root@$addr<<EOF"
    list = "cd /var/www/media\n"
    if($# -eq "2")
    then
        list=list+"mkdir $2\nEOF\n"
    else
        num=2
        i=$(($num))
        while($num < $#)
        do
            i=$(($num))
            list=list+"mkdir $i\n"
            list=list+"cd $i\n"
            $num=$num+1
        done
    fi
    echo $list
elif ($1 -eq "F")
then
    #list = "cd /var/www/media\n"
    f2="rsync -rsh=\'ssh -p22\' "
    f3 = "root@$addr:/var/www/media"
    if($# -eq "2")
    then
        f2=f2+$2+" "+f3
    else
        num=3
        i=$(($num))
        while($num < $#)
        do
            i=$(($num))
            f2=f2+"/"+$i
            $num=$num+1
        done
        i=$(($num))
        f2=f2+$i+" "+$f3
    fi
    echo $f2
fi
exit

输出:

(prompt)$ ./upload2 F SO test.txt
./upload2: line 3: 3: command not found
./upload2: line 6: F: command not found
./upload2: line 25: F: command not found

如您所见,我在处理输入时遇到问题。自从我完成 bash 以来已经有一段时间了。而且它从一开始就不是广泛的。寻找我的问题的解决方案,但也有建议。提前致谢。

4

2 回答 2

2
  1. 为了比较,使用[[ .. ]]. ( .. ) 用于在子shell 中运行命令
  2. 不要-eq用于字符串比较,使用=.
  3. 不要<用于数值比较,使用-lt
  4. 要附加值,f2="$f2$i $f3"
  5. 要添加换行符,$'\n'请在双引号之外使用,或在其中使用文字换行符。
  6. 您总是需要在字符串中的变量上使用“$”来引用它们,否则您会得到文字字符串。
  7. 您不能在=in 分配周围使用空格
  8. 您不能$在赋值中的变量名之前使用
  9. 要进行算术运算,请使用$((..))result=$((var1+var2))
  10. 对于间接引用,例如获取$4for n=4,使用${!n}
  11. 为防止分词删除换行符,请使用双引号变量,例如echo "$line"

考虑编写较小的程序并在构建之前检查它们是否有效。

这是我编写脚本的方式(稍微缺乏参数检查):

#!/bin/bash
addr=$(ifconfig -a | ./test)
if [[ $1 = "DIR" ]]
then
  shift
  ( IFS=/; echo ssh "root@$addr" mkdir -p "/var/www/media/$*"; )
elif [[ $1 = "F" ]]
then
  shift
  last=$#
  file=${!last}
  ( IFS=/; echo rsync "$file" "root@$addr:/var/www/media/$*" )
else
  echo "Unknown command '$1'"
fi

$*为您提供由 中的第一个字符分隔的所有参数$IFS,我用它来构建路径。这是输出:

$ ./scriptname DIR a b c d
ssh root@somehost mkdir -p /var/www/media/a/b/c/d
$ ./scriptname F a b c d somefile.txt
rsync somefile.txt root@somehost:/var/www/media/a/b/c/d/somefile.txt

删除回声以实际执行。

于 2013-06-20T01:59:37.997 回答
2

您的脚本的主要问题是条件语句,例如

if ($# -le "1")

尽管这在其他语言中会发生什么,但在 Bash 中,这实际上是在说,$# -le "1"在子 shell 中执行命令行,并使用其退出状态作为条件。

  • 在您的情况下,扩展为3 -le "1",但该命令3不存在,这会导致错误消息

    ./upload2:第 3 行:3:找不到命令

最接近的有效语法是

if [ $# -le 1 ]

这是主要问题,其他人的帖子中还详细说明了其他问题。

最后一件事,当您为变量赋值时,例如

f3 = "root@$addr:/var/www/media"

不要在=. 上面的语句将被解释为“f3使用="root@$addr:/var/www/media"作为参数运行命令”。

于 2013-06-20T03:35:49.540 回答