Shellscript 可自动复制每个 ftp 上的所有文件

Shellscript 可自动复制每个 ftp 上的所有文件

今天我编写了一个脚本,该脚本应该将每个 ftp 的所有文件复制到我的目标服务器。

脚本是在 zsh-shell 内执行的,所以我想我应该使用“sh script.sh”来正确执行它?

我还将我的脚本粘贴到https://www.shellcheck.net/,这说它很好,但在我的 zsh-shell 中我收到以下错误:

upload_file: command not found

#!/bin/bash

FTP_SERVER=ftp.ip
FTP_USER=ftp.user
FTP_PASS=ftp.passwd

FTP_DESTINATION_DIR="/destination_directory"

LOCAL_SOURCE_DIR="/home/$USER/pictures/local_pictures"

function upload_file {
  local file=$1
  echo "Hochladen von Datei $file"
  ftp -inv "$FTP_SERVER" << EOF
user $FTP_USER $FTP_PASS
binary
cd $FTP_DESTINATION_DIR
put $file
quit
EOF
}

find "$LOCAL_SOURCE_DIR" \( -name "*.jpg" -o -name "*.png" \) -exec bash -c 'upload_file "$0"' {} \;

我不太习惯这种脚本......

答案1

眼前的问题是您声明的函数对于bash您运行的第二个实例不可见find ... -exechttps://shellcheck.net/可能只是看到一个单引号文字字符串,而不是在其中查找问题。

用于sh运行 Bash 脚本也可能是一个问题。除了非标准声明之外,您的脚本不使用任何 Bash 功能function,但实际上没有理由比标准 POSIX 函数声明语法更喜欢它。 (如果sh是您系统上 Bash 的符号链接,即使当它被调用为 时许多仅 Bash 的功能将被关闭,它也可能起作用sh。但您仍然应该理解其中的区别,并用于bash运行 Bash 脚本。)

无论如何,首选机制是chmod +x脚本,然后通过指定其路径(或者仅指定其名称,如果它所在的目录位于您的PATH)来运行它。这允许舍邦选择正确的口译员。 (如果您使用shor显式运行脚本bash,或者甚至是像pythonor 这样完全错误的内容,则它会被简单地忽略为注释csh)。

修复这些细节后,您的脚本将如下所示。

#!/bin/bash

FTP_SERVER=ftp.ip
FTP_USER=ftp.user
FTP_PASS=ftp.passwd

FTP_DESTINATION_DIR="/destination_directory"

LOCAL_SOURCE_DIR="/home/$USER/pictures/local_pictures"

upload_file () {
  local file=$1
  echo "Hochladen von Datei $file"
  ftp -inv "$FTP_SERVER" <<EOF
user $FTP_USER $FTP_PASS
binary
cd $FTP_DESTINATION_DIR
put $file
quit
EOF
}

export -f upload_file

find "$LOCAL_SOURCE_DIR" \( -name "*.jpg" -o -name "*.png" \) -exec bash -c 'upload_file "$0"' {} \;

更好的解决办法仍然是允许upload_file接受多个文件名,并且只创建一个 FTP 会话。

:
upload_file () {
  ( printf '%s\n' \
      "user $FTP_USER $FTP_PASS" \
      "binary" \
      "cd $FTP_DESTINATION_DIR"
    local file
    for file; do
        # print diagnostics to stderr
        echo "Hochladen von Datei $file" >&2
        echo "put $file"
    done
    echo "quit" ) |
  ftp -inv "$FTP_SERVER"
}

export -f upload_file

find "$LOCAL_SOURCE_DIR" \( -name "*.jpg" -o -name "*.png" \) \
    -exec bash -c 'upload_file "$@"' _ {} +

顺便说一句,可能不要.sh在 shell 脚本上使用扩展,特别是当它们实际上不是sh脚本时。对此没有严格的约定,但ls也没有扩展;为什么要这样呢?

答案2

这里的问题是,upload_file该函数仅在您的脚本中可用,但不能导出bashfind.

要解决此问题,您可以导出函数使用这个:

typeset -fx upload_file

将其放在调用find命令之前,它应该按预期工作。


编辑: Tripleee 在评论中指出export -f也可以使用。这无疑更具可读性。

答案3

看来您没有正确声明功能。从输出和行为来看,您缺少括号function upload_file {...应该是function upload_file (){...(在您编辑问题之后,我认为这不再是问题)。在 bash 中,您应该导出该函数,以便在步骤中
执行时它是可见的:bash -cfind

export -f upload_file
find "$LOCAL_SOURCE_DIR"...

正如你所看到的回答

相关内容