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'
notを使用してください。/
set -o extendedglob # for (#m)
find ${refind_efi_dir}drivers_x64/ \
${(@0)${drivers//(#m)[?*[\\]/\\$MATCH}/#/!$'\0'-name$'\0'} \
-type f -exec rm -f {} +
しかし、読みやすさにはあまり役に立ちません...
zsh
ここでは の glob を使ってすべてを表すこともできます。
(cd -P -- $refind_efi_dir && rm -f -- **/^(${(~j[|])drivers})(D.))
ここで、パラメータ拡張フラグは配列j[|]
要素を使用して連結し、グローバル演算子として処理されるようにします。モードが無効になります(このオプションが必要です)。隠しファイルを含みます。$drivers
|
~
|
^
extendedglob
D
.
-type f
答え2
"${drivers[@]/#/! -name }"
! -name
各配列要素に同じシェルワードを入れます。"${=drivers[@]/#/! -name }"
結果を分割するので、!
およびは-name
別のシェルワードで終わりますが、配列要素もスペースに分割されます。
1つの解決策は乱用することですe
。P
グローバル予選:
find … /(e\''reply=($drivers)'\'P\''!'\'P\''-name'\') …
/(…)
/
常に正確に1つのエントリ(ルートディレクトリ)に一致するglobパターンを展開し、ここにglob修飾子を適用します。 glob修飾子は、e
各項目を配列変数の新しい値に置き換えますreply
。この値は、後続のglob修飾子が適用される単語のリストに設定されます。次に、glob修飾子を2回使用して、P
各一致の前に指定されたテキストを別々の単語として挿入します。
この特定のケースではステファン・チャゼラスが示すように、zsh globを使用すると、findを使用せずにすべての操作を実行できます。