
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'
대신 사용하십시오./
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[|]
의 요소를 결합 하고 이를 glob 연산자로 처리하게 합니다. 해당 패턴은 (옵션이 필요함 ) 로 무효화됩니다 . 숨겨진 파일을 포함하려면 .$drivers
|
~
|
^
extendedglob
D
.
-type f
답변2
"${drivers[@]/#/! -name }"
! -name
각 배열 요소와 동일한 쉘 단어를 넣습니다 . "${=drivers[@]/#/! -name }"
결과를 분할하므로 !
및 -name
는 별도의 쉘 단어로 끝나지만 배열 요소도 공백으로 분할됩니다.
한 가지 해결책 e
은P
글로벌 한정자:
find … /(e\''reply=($drivers)'\'P\''!'\'P\''-name'\') …
/(…)
/
항상 정확히 하나의 항목(루트 디렉터리)과 일치하는 glob 패턴을 확장하고 여기에 glob 한정자를 적용합니다. glob 한정자는 e
각 일치 항목을 배열 변수의 새 값으로 대체합니다 reply
. 이 값은 후속 glob 한정자를 적용하려는 단어 목록으로 설정됩니다. 그런 다음 두 번 사용되는 glob 한정자는 P
각 일치 항목 앞에 지정된 텍스트를 별도의 단어로 삽입합니다.
이 특정한 경우에는스테판 차젤라스(Stéphane Chazelas)가 보여준 것처럼, find를 사용하지 않고도 zsh glob으로 모든 작업을 간단히 수행할 수 있습니다.