すべてのFTPのすべてのファイルを自動的にコピーするシェルスクリプト

すべての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実行している2番目のインスタンスには表示されないことですfind ... -exechttps://shellcheck.net/問題を見つけるのではなく、単一引用符で囲まれたリテラル文字列だけを見ることもできます。

Bashスクリプトの実行にsh問題がある可能性があります。あなたのスクリプトは非標準宣言以外のBash機能を使用しませんが、function実際には標準のPOSIX関数宣言構文よりもそれを好む理由はありません。 (shシステムがBashへのシンボリックリンクである場合は、呼び出されたときに多くのBash専用機能がオフになっても機能する可能性がありますが、それでもsh違いを理解し、それを使用してbashBashスクリプトを実行する必要があります。)

いずれにせよ、好ましいメカニズムはスクリプトを作成し、そのパスchmod +x(またはディレクトリがユーザーのものである場合は名前のみ)を指定してPATH実行することです。これを通してシェルボーン正しい通訳を選択してください。 (shまたはを使用してスクリプトを明示的に実行した場合、bashまたはpythonなど、完全に間違っている場合でもコメントとして無視されます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複数のファイル名を許可し、1つの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シェルスクリプトで拡張を使用しないでしょう。特に実際にスクリプトではない場合はさらにそうです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"...

あなたが見たように回答

関連情報