bash는 dir1에서 "find"를 사용하고 dir2에서 이 파일을 삭제합니다.

bash는 dir1에서 "find"를 사용하고 dir2에서 이 파일을 삭제합니다.

두 개의 폴더가 있습니다. 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.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: Nulglob: 일치하는 항목이 없어도 불평하지 마세요. 실제로, 파일이 발견되지 않으면 .ext쉘이 중단되도록 닫을 수도 있습니다 .
  • D: Dotglob: 숨겨진 파일을 건너뛰지 마세요.
  • ^/제외 유형 파일 find과 마찬가지로! -type d목차(먼저 내용을 삭제하지 않으면 삭제할 수 없습니다.)
  • :t: taail 받기, 기본 이름
  • ${(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.extdir2/bar.ext하위 디렉터리의 디렉터리는 제외) 위 명령 **/에서 및 를 제거 rm하거나 GNU find및 다음을 사용하세요 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예상대로 작동한다고 만족스러우면 제거하세요.

관련 정보