8

次のような単純なテスト bash スクリプトがあります。

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
$cmd # execute command

~スクリプトを実行すると、除外するつもりだったのに、で終わるファイルもコピーされます。コマンドラインからまったく同じ rsync コマンドを直接実行すると、うまくいきます! 誰かがbashスクリプトを機能させる理由と方法を知っていますか?

ところで、私も一緒に作業できることは知ってい--exclude-fromますが、とにかくこれがどのように機能するか知りたいです。

4

3 に答える 3

6

evalを試してください:

#!/bin/bash

cmd="rsync -rv --exclude '*~' ./dir ./new"
eval $cmd # execute command
于 2009-05-11T13:21:48.000 に答える
5

問題は、スクリプトで実行していることではなく、コマンドを変数に入れてから、展開された変数を実行することです。また、引用符の削除が既に行われた後に変数の展開が行われるため、除外パターンを囲む単一引用符は削除されません...そのため、rsync は、' で始まり ~' で終わる名前のファイルを除外してしまいます。これを修正するには、パターンを囲む引用符を削除します (全体がすでに二重引用符で囲まれているため、必要ありません)。

#!/bin/bash

cmd="rsync -rv --exclude *~ ./dir ./new"
$cmd # execute command

...そういえば、なぜコマンドを実行する前に変数に入れているのですか? 一般に、これはコードを必要以上に混乱させ、奇妙な構文解析を引き起こす良い方法です (これよりも奇妙なものもあります)。それではどうですか:

#!/bin/bash

rsync -rv --exclude '*~' ./dir ./new
于 2009-05-11T21:03:34.187 に答える
0

単純な--eclude '~'as を使用できます (man ページによると):

  • パターンが / で始まる場合は、ファイルの階層内の特定の場所に固定されます。それ以外の場合は、パス名の末尾と照合されます。これは、正規表現の先頭の ^ に似ています。したがって、「/foo」は、「転送のルート」(グローバル ルールの場合) またはマージ ファイルのディレクトリ (ディレクトリごとのルールの場合) の「foo」の名前と一致します。アルゴリズムが上から下に再帰的に適用されるため、修飾されていない "foo" は、ツリー内の任意の場所にある "foo" の名前と一致します。各パス コンポーネントがファイル名の最後で順番を取得するかのように動作します。固定されていない「sub/foo」でさえ、「sub」という名前のディレクトリ内で「foo」が見つかった階層内の任意のポイントに一致します。
  • パターンが / で終わる場合、通常のファイル、シンボリック リンク、またはデバイスではなく、ディレクトリにのみ一致します。
  • rsync は、パターンに次の 3 つのワイルドカード文字 (「*」、「?」、および「[」) のいずれかが含まれているかどうかをチェックすることにより、単純な文字列一致とワイルドカード一致のどちらを実行するかを選択します。
  • 「*」は任意のパス コンポーネントに一致しますが、スラッシュで終わります。
  • '**' を使用して、スラッシュを含むあらゆるものに一致させます。
于 2009-05-11T11:56:56.417 に答える