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}"