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'
not을 사용하십시오./
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[|]
요소를 사용하고 연결하여 전역 연산자로 처리되도록 합니다. 모드가 무효화됩니다(이 옵션이 필요함). 숨겨진 파일을 포함하며 .$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)가 보여주는 것처럼, zsh glob을 사용하면 find를 사용하지 않고도 모든 작업을 수행할 수 있습니다.