2つのフォルダがあります。 dir1で特定の拡張子を持つファイルを繰り返し見つけ、dir2からdir1のファイルを削除したいと思います。 findで-execコマンドを使用すると、これを行うことができると思います。 dir1から削除するのはとても簡単です。しかし、dir2ではどうしますか?
/home/admin/.cache/yay/ -name '*.pkg.tar.zst' -exec basename {} を探します (現在 /tmp/test/ にあるファイルを削除します)。
答え1
簡単に見えるxargs
:
(cd dir1 && find . -name '*.ext' ! -type d -print0) |
(cd dir2 && xargs -r0 rm -f --)
同じ合計のすべてのfoo.ext
合計に対して削除されます。subdir/bar.ext
dir1
foo.ext
subdir/bar.ext
dir2
dir1
と同じディレクトリにない場合でも、同じ名前のファイルを削除したい場合dir2
(例:上記の例ではすべて削除dir2/bar.ext
、dir2/any/level/of/subdirectory/foo.ext
)zsh
:
typeset -U names
names=( dir1/**/*.ext(ND^/:t) )
rm -f -- dir2/**/(${(~j[|])names})(D^/)
typeset -U names
与えられたユニーク配列として割り当てるときに要素を一意にする変数のプロパティ(重複排除)。**/
すべてのレベル(レベル0を含む)サブディレクトリN
:N
ulglob:一致するものがなくても文句を言わないでください。実際、ファイルが見つからない場合は、.ext
シェルを中断するように閉じることもできます。D
:D
otglob:隠しファイルをスキップしないでください。^/
除外タイプファイルfind
と同様! -type d
目次(最初に内容を削除しないと削除できません。):t
:t
aailを受け取る、デフォルト名${(j[string])array}
配列の要素をstring
中間要素に関連付けます。を使用すると、~
連結された文字列はglob演算子として扱われ、最終的にglobになります(foo.ext|bar.ext|...)
。
匿名関数を使用し、u
それをパラメータ拡張フラグに置き換えて、typeset -U
次のコマンドで同じゴルフボールを打ちます。
(){rm -f dir2/**/(${(~j[|])${(u)@}})(D^/)} dir1/**/*.ext(D^/:t)
異なる名前が多い場合、より効率的な別のアプローチは、連想配列を使用することです。
typeset -A to_remove
: dir1/**/*.ext(ND^/e['to_remove[$REPLY:t]=1'])
rm -f -- dir2/**/*.ext(De['(( $to_remove[$REPLY:t] ))']^/)
ルートディレクトリからのみ削除するにはdir2
(上記の例ではdir2/foo.ext
サブdir2/bar.ext
ディレクトリのディレクトリを除く)、上記のコマンドから削除**/
するrm
か、またはGNUfind
と次を使用しますsort
。
(cd dir1 && find . -name '*.ext' -printf '%f\0') |
LC_ALL=C sort -zu |
(cd dir2 && xargs -r0 rm -f --)
答え2
dir1でファイルパスを探します。パスをファイル名でのみ削除します。 dir2で見つかったすべてのファイルを削除します。
find /home/admin/.cache/yay/ -type f -name '*.pkg.tar.zst' -exec sh -c 'for f in "$@"; do echo rm -f -- "/path/to/dir2/${f##*/}"; done' _ {} +
シェルループを望まない場合は、
find /home/admin/.cache/yay/ -type f -name '*.pkg.tar.zst' -exec sh -c 'echo rm -f -- "/path/to/dir2/${1##*/}"' _ {} \;
echo
期待どおりに機能すると満足している場合は削除してください。