もちろん私は簡単なものを見逃していますが、それは私を狂わせます。リモートファイルを現在のローカルディレクトリにSCPに送信しようとしています。リモートパスにスペースがあります。ファイルから読み取るため、スクリプトで実行し、パスを変数に入れる必要があります。
問題は、エスケープしようとしても、「ファイルまたはディレクトリが見つかりません」というエラーが引き続き発生することです。-v
コマンドにオプションを追加しscp
てコピーして貼り付けると、コマンドは機能しますが、そこに変数があると爆発します。
パスを作成すると正常に機能しますが、パスを変数に入れようとすると操作が中断されます。ハードコーディングされた文字列をエスケープすることに関する同様の質問がたくさんありますが、ファイルパスにスペースがある変数を使用する質問は見つかりません。
ファイルパスは次のとおりです。
/home/myUser/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
verbose を実行すると、scp
この行は以下をsending command
印刷します。
scp -f /home/myUser/databases/SONIC\\ BOATS\\ LTD./database-1.11-2019-12-30-09-40.zip .
その行をスクリプトに貼り付けて実行すると機能します。それでは、変数があるスクリプトで実行するとなぜ動作しませんか?
私の変数は次のように印刷されます。
DB_ARC_FILENAME:
/home/myUser/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
ESC_DB_ARC_FILENAME
/home/myUser/databases/SONIC\ BOATS\ LTD./database-19.11-2019-12-30-09-40.zip
私のスクリプトコードスニペット:
while read DB_ARC_FILENAME
do
# Escape spaces in the files name
ESC_DB_ARC_FILENAME=${DB_ARC_FILENAME//\ /\\\ }
# Copy the database file to the local system
scp -v [email protected]:"$ESC_DB_ARC_FILENAME" .
...
done < uploadedDatabaseFileList
これは私が実行したときに得られる結果です。
debug1: Sending command: scp -v -f /home/myUser/databases/SONIC\\ BOATS\\ LRD./database-1.11-2019-12-30-09-40.zip
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype [email protected] reply 0
: No such file or directoryer/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
debug1: channel 0: free: client-session, nchannels 1
: No such file or directoryes/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 2836, received 2704 bytes, in 0.8 seconds
Bytes per second: sent 3678.9, received 3507.7
debug1: Exit status 1
答え1
脱出パターンが正しくありません。各スペースの前にバックスラッシュを追加するこのオプションを使用します。
ESC_DB_ARC_FILENAME="${DB_ARC_FILENAME// /\\ }"
テストシナリオ(中$HOME
):
file='the date.txt'
date > "$file"
scp -vp localhost:"$file" td; ls -l td; rm -f td # Fails
scp -vp localhost:"${file// /\\ }" td; ls -l td; rm -f td # Succeeds
知っていた。このエラーメッセージはこれを知らせます。
: No such file or directoryes/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip
Windowsコンピュータで生成されたソースデータファイルを使用しています。もちろん、ソースファイルにはそのような文字はありませんが、末尾のCRはファイル名の一部と見なされます。
答え2
Bashスクリプトを使用してスペースを含むリモートパスからファイルをコピーしようとしたときにscp
同様の問題が発生しました。
私が思いついた解決策は次のとおりです。
二重引用符+オプションを使用してください-T
。
scp -T user@host:"'<path-with-spaces>'" <destination>
scp -T user@host:'"<path-with-spaces>"' <destination>
scp -T user@host:"\"<path-with-spaces>\"" <destination>
注:オプションがない場合、-T
これらのコマンドはprotocol error: filename does not match request
理由を詳しく説明します。ここ。
printfのエスケープパスを使用してください。
source="<path-with-spaces>"
printf -v source "%q" "${source}"
scp user@host:"${source}" <destination>
注:このオプションはオプションなしでうまく機能します-T
が、単一のファイルに対してのみ機能します。複数のファイルの場合は、-T
オプションが必要です(上記と同じエラー)。