
scp
ファイルをコピーするために使用できる式を構成する方法はありますか?
file-name-version-1.2.1.jar
ファイルをコピーする必要はありません。
file-name-version-1.2.1-sources.jar
file-name-version-1.2.1-javadoc.jar
しかし、正しいバージョン番号がわからないのですか?file-name-version-*.*.*.jar
明らかな理由で動作しません。私は次の構文を探しています。
file-name-version-\d.\d.\d.jar
またはそのようなもの。
答え1
覚えておくべき1つは、ファイル名が渡されることです。変更されていないリモートユーザーのログインシェルとして。
これにより:
scp user@remote-machine:'something' ...
リモートシステムでは、sshd
次のログインシェルが実行されますuser
。
that-shell -c 'scp -f something'
その中のパターンを拡張するのがまさにこの殻です。
つまり、パターン拡張方法は、リモートユーザーが使用するログインシェルによって異なります。そのシェルがある場合、bash
ユーザーが~/.bashrc
何を持っているのか、それに何があるのかによって異なります/etc/bash.bashrc
(たとえば、bash-completion
インストール中にそこから呼び出すと、kshスタイルの拡張ワイルドカードがオンになります)。呼び出し時に何らかの理由でbash
これらの内容を読み取るためssh
です(これは対話型シェルです)。
これはまた、something
これが真であれば'blah; rm -rf "$HOME"'
悲惨な結果をもたらすことを意味します。
これは設計エラーの1つですssh
。
something
特定のシェルを強制的にファイルのリストに拡張するには、次の方法を使用できます。
LC_SCPFILES=something scp -o SendEnv=LC_SCPFILES "localhost:</dev/null
bash -O extglob -c 'exec scp -f -- \$LC_SCPFILES';exit" /dest/dir
リモートユーザーのログインシェルが通常のUnixシェル(少なくともBourne、csh、rc、またはFishファミリ)であり、ここにインストールされていてbash
名前sshd
を渡すことができる場合にのみ適用されますLC_
。
ヒントは、ほとんどのsshd
展開では、名前が次に始まる環境変数を渡すことを許可することLC_
です。これは、スペイン語を使用するユーザーがリモートシステムのデフォルト言語やリモートユーザーの言語ではなく、スペイン語のリモートコマンドからエラーメッセージを受け取るようにするために必要です。 )) 。
ここでは環境変数を渡しsomething
ますLC_SCPFILES
。
リモートシステムで次をsshd
実行します。
that-shell -c 'scp -f </dev/null
bash -O extglob -c '\''exec scp -f -- $LC_SCPFILES'\'';exit'
/dev/null
最初のものは標準入力がからリダイレクトされるのでscp
すぐに終了します。次に、オプションを使用して選択したシェルを起動し、解釈にbash
コマンドラインをextglob
使用します。exec scp -f -- $LC_SCPFILES
サブプロセス(後で追加して強制実行)bash
で実行されるため、ソースは提供されないため、デフォルトの動作が期待できます(起動時または環境変数が何らかの方法で設定されていない限り)。that-shell
;exit
bash
~/.bashrc
bash
that-shell
BASHOPTS
SHELLOPTS
BASH_ENV
引用符がないため、$LC_SCPFILES
トークン化とファイル名の生成(ワイルドカード)の影響を受けますが、他のシェル拡張の影響を受けず、埋め込まれても同様のことはrm -rf "$HOME"
しsomething
ません。
パターンがリモートシステムで拡張されていることを確認したので、拡張bash -O extglob
glob演算子(ここでヘルパー関数を使用)を使用してパターンを一致させることができます。
safer_scp() (
file=$1; shift
export LC_SCPFILES="${file#*:}"
exec scp -o SendEnv=LC_SCPFILES "${file%%:*}:</dev/null
bash -O extglob -c 'exec scp -f -- \$LC_SCPFILES';exit" "$@"
)
safer_scp user@host:'file-name-version-+([0-9]).+([0-9]).+([0-9]).jar' .
on を使用すると、+([0-9])
1 つ以上の小数点以下の桁数と一致します。たとえば、上記のパターンは一致します。extglob
bash
file-name-version-1.2.3.jar
file-name-version-12.123.1234.jar
(上記では、safer_scp
最初の引数があり、または同じものは機能しないと仮定しますhost:file-patterns
。safer_scp -r ...
safer_scp host1:f1 host2:f2 ...
-r
safer_scp_r
scp -f
scp -r -f
IFS=;
上記の単語の区切りを追加すると、単語の区切りを無効にできますexec scp...
。
また、すべてのGNUシステムにインストールされているので、ここで使用していますが、リモートシステムにインストールされていることがわかっている場合は、bash
次のものを使用できます。zsh
zsh -o extendedglob -o globsust
zsh
代わりに、ワイルドカード(再帰、修飾子...)のすべての機能を活用してください。
(-o shwordsplit
単語分割も必要な場合は追加)。
たとえば、
safer_scp() (
file=$1; shift
export LC_SCPFILES="${file#*:}"
exec scp -o SendEnv=LC_SCPFILES "${file%%:*}:</dev/null
zsh -o extendedglob -o globsubst -c 'exec scp -f -- \$LC_SCPFILES';exit" "$@"
)
safer_scp user@host:'file-name-version-<->(.<->)#.jar' .
は から までの任意の 10 進整数file-name-version-1.jar
であり、正規表現演算子のような任意の 10 進整数です (0 以上の先行原子)。file-name-version-1.2.3.4.5.jar
<x-y>
x
y
<->
#
*
答え2
この特別なケースでは
scp 'user@host:file-name-version-*[0-9].jar' .
それだけで十分でしょう。
答え3
私の考えでは、あなたが欲しいと思います。
file-name-version-[0-9].[0-9].[0-9].jar
答え4
柔軟性のために、以下を使用してください。同期SCPの代わりに。
rsync --include='file-name-*.jar' \
--exclude='*-sources.jar' --exclude='*-javadoc.jar' \
example.com:/some/directory/ local/directory/