rsyncを使用して選択したパターンを削除し、すべてのファイルと一致

rsyncを使用して選択したパターンを削除し、すべてのファイルと一致

rsync特定のファイルを削除することを意味します(例:何千ものファイルを含む大規模ディレクトリを効率的に削除します。)、この場合はコマンドラインのパターンとしてシェルスクリプトに割り当てられます。

これがこれまで私のシェルスクリプトにあります。rsync_del.sh

#!/bin/bash

TARGET_DIR=${1}
shift
PATTERNS="${@}"
for patt in ${PATTERNS} ; do
    # Both do the same
    #INCLUDE_PATTERNS="${INCLUDE_PATTERNS}"' --include='\'"${patt}"\'
    INCLUDE_PATTERNS="${INCLUDE_PATTERNS} --include=\"${pattern}\""
done

EMPTYDIR=$(mktemp -d)
echo "Created empty dir ${EMPTYDIR}"
comm="rsync -a --progress --delete ${INCLUDE_PATTERNS} ${EMPTYDIR}/ ${TARGET_DIR}"
echo ${comm}
eval ${comm}

私が使用したいサンプルパターンは*[1-9].txt、です*000??9.txt。問題は実行時に

rsync_del.sh trg_dir '*[1-9].txt'

生成されたコマンドラインは次のとおりです。

rsync -a --progress --delete --include='*[1-9].txt' /tmp/tmp.51R9hPgkfG/ trg_dir/

(私は見るのは大丈夫だと思いますが)たとえば、似たようなファイルと一致するものですinput.dat(私はそれを望んでいません)。

これを実装/使用する正しい方法は何ですか? パターンを正しくエスケープするのに問題があるようですが、そうすることはできません。

echo注:実行するコマンドを実行する前に、変数で定義する必要があります。

答え1

実際の状況をあまり詳しく見ていない使用ここでは、rsync代わりにコマンドラインの作成に焦点を当てますrsync

#!/bin/bash

target=$1
shift

empty=$( mktemp -d )

trap 'rmdir "$empty"' EXIT

for pattern do
   incl+=( --include="$pattern" )
done

rsync --archive --progress --delete "${incl[@]}" --exclude='*' "$empty"/ "$target"

配列(incl上記)を使用すると、rsync同じ文字列の代わりにパラメータを個別に保存できます。拡張は"${incl[@]}"配列で個別に参照される要素になります。パラメータの引用は簡単で、呼び出しは必要ありませんeval。さらに、すべてのパラメータ拡張には正しい二重引用符が必要です。

コードの問題は、ほとんど引用されていないパラメータ拡張を使用することです。これにより、シェルは変数に対してトークン化とファイル名の生成(グローバル化)を実行します。これは、スペースを含むパターンまたは既存のファイル名に拡張できるシェルワイルドカードパターンを使用できないことを意味します。


/bin/sh構文がより簡潔になるからです。

#!/bin/sh

target=$1
shift

empty=$( mktemp -d )

trap 'rmdir "$empty"' EXIT

for pattern do
   set -- "$@" --include="$pattern"
   shift
done

rsync --archive --progress --delete "$@" --exclude='*' "$empty"/ "$target"

答え2

明示的に含まれていない項目を除いてパターンリストを閉じる必要があることを忘れました。使った

comm="rsync -a --progress --delete ${INCLUDE_PATTERNS} --exclude=\"*\" ${EMPTYDIR}/ ${TARGET_DIR}"

関連情報