検索結果を変数に保存してcpに渡しますか?

検索結果を変数に保存してcpに渡しますか?

経過時間に基づいてファイルセットを処理する必要があります(リモートディレクトリに新しいファイルが追加されるタイミングを制御できないため)。

ファイルセットに対して複数のタスクを実行する必要があるため、find結果を変数に保存して(該当する候補が変更されないようにすることができます)、各タスクにfind同じリストを使用しました(別のタスクを実行する必要はありません)。やり直す)。

これは私が試しているものの簡単なバージョンです。

FILELIST=$(ssh ${SSHUSER}@${SSHHOST} "cd ${REMOTEPATH}; find -amin +${TIME} -type f,d -print")

if [[ ${#FILELIST} -lt 4 ]]; then
  echo "No files" >> ${LOGFILE}
  exit 1
fi

echo -en "Copying remote files to remote backup\n" >> ${LOGFILE}
ssh ${SSHUSER}@${SSHHOST} "cd ${REMOTEPATH}; cp -Rpv '${FILELIST}' ${REMOTEBACKUPPATH}" >> ${LOGFILE}

これは間違いなく私がcp: missing destination file operand after ''理解することを提供します。cp私が望む方法でファイルリストをフォーマットする方法がわかりません。

私は文書/ SEの記事を読んでしばらくこれをやってきましたが、理解できません。私が何を間違っているのかがわかったら、cpその知識をに適用できることを願っていますrsync

まだ明確ではない場合、私は初めてbashスクリプトの世界に触れました。 :)

よろしくお願いします。

ベストアンサー1

bashこの問題を解決するのに最適なシェルではありません。代わりに提案します(いくつかのパラメータ拡張を引用せずに構文をすでに使用していますzsh)。zsh

filelist=(
  ${(0)"$(
    ssh $SSHUSER@$SSHHOST "
      cd -- ${(qq)REMOTEPATH} &&
        find . -amin +${TIME} -type f,d -prune -print0"
  )"}
)

if (( $#filelist < 4 )); then
  print No files >> $LOGFILE
else
  print "Copying remote files to remote backup" >> $LOGFILE
  print -rNC1 -- $filelist | ssh $SSHUSER@$SSHHOST "
    cd -- ${(qq)REMOTEPATH} && xargs -r0 cp -Rpvt ${(qq)REMOTEBACKUPPATH}"
fi

$SSHHOSTこれがGNUシステムであると仮定し(あなたはすでにいくつかのGNUismを使用しています。たとえば、ファイルは、f,dに渡されません))ログインシェルはBourneのようなものです。findcp -v$SSHUSER

とにかくこのディレクトリ全体をコピーするので、その中にさらにファイルを見つける必要がないので、それをコマンドに追加しまし-pruneた。findこれらのディレクトリの内容を読み取ると、最後のアクセス時間も更新されます。

それにもかかわらず、ディレクトリのファイルを読み込んでも、ディレクトリのアクセス時間は更新されません。ディレクトリのアクセス時間は、ディレクトリ内のシェルまたはグローバルls変数を使用する場合と同様に、ディレクトリ自体の内容を読み取ると更新されますfind(最近のアクセス時間は必ずしも完全に維持されるわけではありません)。それで、正確に何をしたいのかは明確ではありません。

上記では、次を使用します。

  • filelist=( values )定義する大量にfilelist=value変数(スカラー代わりに変数)。
  • ${(0)"$(cmd)"}cmdNULから出力を分割します。 NULはファイルパスに許可されていない唯一の文字なので、NULで区切られたリストを使用することはファイルパスリストを渡す安全な方法です。
  • cd -- ${(qq)REMOTEPATH}、で始まる値(それ自体ではありませんが/一部のシェルでは)と引用符付きの値(ここではデフォルトのシェルによって拡張されます)を--防ぐために(、$REMOTEPATH---4+3$REMOTEPATHqq唯一の安全な方法$REMOTEPATH)リモートシェルの場合(Bourneに似ていると仮定し、ログインシェルがcsh / fish / rc ...の場合、一部の値では機能しません$SSHUSER。)
  • &&成功した場合にのみ、次のコマンドが実行されることを保証します。cdそれ以外の場合は、間違ったディレクトリで実行されます。
  • -print0:NULで区切られたファイルパスを印刷します(上記を参照)。
  • これは一致するファイルの数を$#filelist含みます(元のコードの4つと比較しましたが、理由はわかりません)。
  • その後、そのリストをリモートホストに再送信する必要があります。これをリモートシェル用に送信されたシェルコードの引数として渡すのではなく(さまざまな問題や制限が発生する)、stdinにprint -NNULで区切って渡します。sshこれは継承されます。xargs
  • xargsリストを読み、それを引数cp -t target-tGNU拡張)に変換します。パラメータサイズの制限を避けるために必要なだけxargs多くを実行してください。cp

おすすめ記事