以下は、あるディレクトリから別のディレクトリにファイルをコピーするUbuntu 18.04のスクリプトです。現在のディレクトリ()のファイルがターゲット/media/rmerriam/Backup/rsync_backup
にコピーされることを除いて、すべてがうまく機能します。ソースパスにまったくないので、まったくコピーしてはいけません。
手動実行(有無にかかわらず-s
):
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ rsync -auv -s ../src/ ../dest
sending incremental file list
sent 59 bytes received 12 bytes 142.00 bytes/sec
total size is 0 speedup is 0.00
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
実行されたスクリプトには次のものはありません-s
。
===========================
./merge.sh
../src/
../dest
rsync -auv ../src/ ../dest
sending incremental file list
./ <====== added why???
merge.sh
merge_all.sh
merge_backups.sh
sent 3,124 bytes received 76 bytes 6,400.00 bytes/sec
total size is 2,835 speedup is 0.89
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
merge_all.sh merge_backups.sh merge.sh
オプションを使用してスクリプトを実行します-s
。
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ./merge.sh ../src/ ../dest -s
===========================
./merge.sh
-s
../src/
../dest
rsync -auv -s ../src/ ../dest
sending incremental file list
./
sent 66 bytes received 19 bytes 170.00 bytes/sec
total size is 0 speedup is 0.00
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
結果:手動実行とオプションでファイルが-s
移動されませんでした。スクリプト$PWD
が存在しない場合、-s
ファイルはコピーされます。
スクリプトは-s
この./
ディレクトリをソースディレクトリとして追加しません。なぜ?
コマンドラインは次echo
のように表示され、同じです。スクリプトに異なる動作があるのはなぜですか?
スクリプトは次のとおりです。
#!/bin/bash
# base script for copying files to the common directory.
# only copies newer files
printf '===========================\n'
printf "$0\n $3\n $1\n $2\n"
echo rsync -auv "$3" "$1" "$2"
rsync -auv "$3" "$1" "$2"
参考までに:rsync version 3.1.2 protocol version 31
答え1
スクリプトにバグがあります。間違いなくrsyncにもバグがあります。なぜなら、奇妙なデータを渡すと静かに驚くべきことをして、ちょうど間違っているように置く方が良いからです。しかし、どちらの方法でもスクリプトは機能しません。
問題のある行は次のとおりです。
rsync -auv "$3" "$1" "$2"
これは、script()"$3"
の3番目の引数がaで始まる場合の-
rsyncのオプションです。ただし、3番目の引数がaで始まらない場合-
(スクリプトに引数が2つ(またはそれ以下)しかない場合を含む)は、オプションではなく引数です。 Rsyncは複数のソースディレクトリを許可するため、"$3"
aで始まらない場合はコピーを-
要求します。"$3"
"$1"
"$2"
./merge.sh ../src/ ../dest
../src/
rsyncに空の文字列を../dest
。
ほとんどのアプリケーションは、ファイル名が見つかると空の文字列を拒否します。ただし、空の文字列がファイル名として受け入れられるたびに、これは現在のディレクトリを表します。これは、相対パスが絶対パスに変換される方法と一致します。パスが相対パスの場合(で始まらない/
)、現在の作業ディレクトリの絶対パスの前にスラッシュを追加すると、同等の絶対パスが得られます。これを空の文字列(スラッシュで始まらないので相対パス)に適用すると、最後にスラッシュがある現在の作業ディレクトリ、つまり現在の作業ディレクトリが得られます。
Rsyncは空の文字列を現在のディレクトリとして受け入れます。だからあなたが言ったものとまったく一致します。
空の文字列をパラメータとして渡すことは、意図的なものよりもバグである可能性が高いです。現在のディレクトリを指定する最も短く、広く使用されている方法は.
(ドット)です。したがって、rsyncは、パラメータが無効であり、エラーが発生したというエラーメッセージを印刷する必要があると言うことができます。
スクリプトでオプションの追加オプションを許可したいが、それを実装する方法によれば、追加オプションは必須です。オプションとして作成するには、スクリプトに3番目のパラメータがあることを確認してください。
if [ $# -lt 2 ]; then
echo >&2 "$0: too few arguments (SRC and DEST are required)"
exit 120
elif [ $# -eq 2 ]; then
rsync -auv "$1" "$2"
elif [ $# -eq 3 ]; then
rsync -auv "$3" "$1" "$2"
else
echo >&2 "$0: too many arguments (only one OPTIONS argument is permitted)"
exit 120
fi
しかし、インターフェイスは奇妙です。なぜ最大1つのオプションを許可するのですか?さまざまなオプションを受け入れることもできます(なぜ通過できないのですか-q --dry-run
?)。これは、ユーザーが理解しやすく、実装するのも簡単です。さらに、慣習はオプションを渡すことです。今後オプションではない引数、それ以降ではありません。インターフェイスが単純化され、さまざまなオプションに対応できるようになったら、コードを単純化して次のようにすることができます。
rsync -auv "$@"
答え2
行って問題を確認しrsync
て確認します"空の引用符は、SRCディレクトリにcwdを追加します。"。$3
追加オプションを追加するスクリプトに問題があります。普通は空いていてそれが犯人ですね。 Addedは-s
パラメータをnull以外にし、この問題を回避します。
この手動実行で問題が確認されました。
rsync "" -auv ../src/ ../dest
sending incremental file list
created directory ../dest
./
merge.sh
merge_all.sh
merge_backups.sh
sent 3,124 bytes received 106 bytes 6,460.00 bytes/sec
total size is 2,835 speedup is 0.88