今天我编写了一个脚本,该脚本应该将每个 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 ... -exec
。https://shellcheck.net/可能只是看到一个单引号文字字符串,而不是在其中查找问题。
用于sh
运行 Bash 脚本也可能是一个问题。除了非标准声明之外,您的脚本不使用任何 Bash 功能function
,但实际上没有理由比标准 POSIX 函数声明语法更喜欢它。 (如果sh
是您系统上 Bash 的符号链接,即使当它被调用为 时许多仅 Bash 的功能将被关闭,它也可能起作用sh
。但您仍然应该理解其中的区别,并用于bash
运行 Bash 脚本。)
无论如何,首选机制是chmod +x
脚本,然后通过指定其路径(或者仅指定其名称,如果它所在的目录位于您的PATH
)来运行它。这允许舍邦选择正确的口译员。 (如果您使用sh
or显式运行脚本bash
,或者甚至是像python
or 这样完全错误的内容,则它会被简单地忽略为注释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
该函数仅在您的脚本中可用,但不能导出bash
到find
.
要解决此问题,您可以导出函数使用这个:
typeset -fx upload_file
将其放在调用find
命令之前,它应该按预期工作。
编辑: Tripleee 在评论中指出export -f
也可以使用。这无疑更具可读性。
答案3
看来您没有正确声明功能。从输出和行为来看,您缺少括号function upload_file {...
应该是function upload_file (){...
(在您编辑问题之后,我认为这不再是问题)。在 bash 中,您应该导出该函数,以便在步骤中
执行时它是可见的:bash -c
find
export -f upload_file
find "$LOCAL_SOURCE_DIR"...
正如你所看到的回答。