bashはdir1で「find」を使用し、dir2からこのファイルを削除します。

bashはdir1で「find」を使用し、dir2からこのファイルを削除します。

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.extdir1foo.extsubdir/bar.extdir2

dir1と同じディレクトリにない場合でも、同じ名前のファイルを削除したい場合dir2(例:上記の例ではすべて削除dir2/bar.extdir2/any/level/of/subdirectory/foo.extzsh

typeset -U names
names=( dir1/**/*.ext(ND^/:t) )
rm -f -- dir2/**/(${(~j[|])names})(D^/)
  • typeset -U names与えられたユニーク配列として割り当てるときに要素を一意にする変数のプロパティ(重複排除)。
  • **/すべてのレベル(レベル0を含む)サブディレクトリ
  • NNulglob:一致するものがなくても文句を言わないでください。実際、ファイルが見つからない場合は、.extシェルを中断するように閉じることもできます。
  • DDotglob:隠しファイルをスキップしないでください。
  • ^/除外タイプファイルfindと同様! -type d目次(最初に内容を削除しないと削除できません。)
  • :ttaailを受け取る、デフォルト名
  • ${(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期待どおりに機能すると満足している場合は削除してください。

関連情報