
rsync
配列で指定されたいくつかのファイルを上書きし、ディレクトリ内の他のファイルを削除したいと思います。
私が考えられる唯一のアプローチは、、、を使用して他のファイルを削除しfind
、rsync
コピーするファイルをできるだけ少なくすることです。
次の例では、と/tmp/tmp/
を除く内の他のすべてのファイルを削除します。btrfs_x64.efi
iso9660_x64.efi
$ refind_efi_dir='/tmp/tmp/'
$ drivers=('btrfs_x64.efi' 'iso9660_x64.efi')
$ find ${refind_efi_dir}drivers_x64/ "${drivers[@]/#/! -name }" -type f -exec rm -f {} +
展開を次のコマンドに展開します。
$ find /tmp/tmp/drivers_x64/ ! -name btrfs_x64.efi ! -name iso9660_x64.efi -type f -exec rm -f {} +
しかし、代わりに次のコマンドを実行しているようです。
$ find /tmp/tmp/drivers_x64/ "! -name btrfs_x64.efi" "! -name iso9660_x64.efi" -type f -exec rm -f {} +
前者を取得する方法はありますか? 理想的には、配列エントリの一部にスペースが含まれている場合にも機能します。
答え1
find
はい、ここでは配列の各要素に対して3 つの引数を生成する必要があります。またfind
、 はパターンを取るため、正確なファイル名に一致させるには、ワイルドカード演算子 ( 、、 )-name
をエスケープする必要があります。find
*
?
[
\
set -o extendedglob # for (#m)
exclusions=()
for name ($drivers) exclusions+=(! -name ${name//(#m)[?*[\\]/\\$MATCH})
find ${refind_efi_dir}drivers_x64/ $exclusions -type f -exec rm -f {} +
"${array[@]/pattern/replacement}"
各要素に対して置換が実行された後、配列内の要素と同じ数だけ展開されます。
ここで、-name
ファイル名前パターンには が含まれていてはならない/
ため、各要素を に置き換えてから で!/-name/element
分割することができます/
。
set -o extendedglob # for (#m)
find ${refind_efi_dir}drivers_x64/ \
${(@s[/])${drivers//(#m)[?*[\\]/\\$MATCH}/#/!\/-name\/} \
-type f -exec rm -f {} +
または、外部コマンドに引数として渡すことができないため、$'\0'
代わりにを使用します。/
set -o extendedglob # for (#m)
find ${refind_efi_dir}drivers_x64/ \
${(@0)${drivers//(#m)[?*[\\]/\\$MATCH}/#/!$'\0'-name$'\0'} \
-type f -exec rm -f {} +
しかし、それは読みやすさにはあまり役立ちません...
ここでは、zsh
すべてに対して のグロブを使用することもできます。
(cd -P -- $refind_efi_dir && rm -f -- **/^(${(~j[|])drivers})(D.))
パラメータj[|]
拡張フラグは、配列の要素$drivers
を で結合し|
、~
それを|
glob 演算子として扱うようにします。このパターンは、^
(オプションが必要ですextendedglob
) で否定されます。をD
使用すると隠しファイルを含めることができ、.
のような通常のファイルに制限することができます-type f
。
答え2
"${drivers[@]/#/! -name }"
! -name
各配列要素と同じシェル ワードを配置します。 は結果"${=drivers[@]/#/! -name }"
を分割するため、!
と は-name
別々のシェル ワードになりますが、配列要素も空白で分割されます。
一つの解決策はe
、P
glob 修飾子:
find … /(e\''reply=($drivers)'\'P\''!'\'P\''-name'\') …
/(…)
glob パターンを展開します/
。これは常に 1 つの対象 (ルート ディレクトリ) に一致し、それに glob 修飾子を適用します。glob 修飾子は、e
各一致を配列変数の新しい値に置き換えますreply
。この配列変数は、後続の glob 修飾子を適用する単語のリストに設定します。次に、P
2 回使用される glob 修飾子は、各一致の前に指定されたテキストを個別の単語として挿入します。
この特定のケースでは、ステファン・シャゼラスが示したように、find を使用せずに、zsh globs ですべてを実行できます。