두 개의 폴더가 있습니다. 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
하거나 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
예상대로 작동한다고 만족스러우면 제거하세요.