매개변수로 전달된 일부 특정 파일을 제외한 파일을 삭제하는 방법은 무엇입니까?

매개변수로 전달된 일부 특정 파일을 제외한 파일을 삭제하는 방법은 무엇입니까?

작업은 n+1개의 인수를 사용하는 쉘 스크립트를 작성하는 것입니다. 여기서 첫 번째 인수는 디렉토리이고 나머지는 지정된 파일이며 지정된 파일을 제외한 모든 파일을 삭제합니다.

예를 들어 전화를 걸어보세요.rmexcept . '*.jpg' '*.png'

cd $1
for i in “${@:2}”
do 
find . -type f -not -name $i -delete
done 

이것이 나의 시도이다. 그러나 지정된 파일 1개(예 rmexcept . '*.jpg': )에 대해서만 작동합니다. 파일이 2개 이상인 경우(예 rmexcept . '*.jpg' '*.png': ) 모든 파일이 삭제됩니다. for 루프를 생성했다고 믿기 때문에 무엇이 잘못되고 있는지 모르겠습니다.

답변1

이것을 시도해 보십시오(댓글은 인라인):

#!/bin/bash                                                                     
set -f     # Prevent e.g. *.txt from being expanded here

dir=$1     # Get the target directory and
shift      # remove from list of args

cmd="find $dir -type f"
while (( "$#" ))              # While there are more arguments left
do
    cmd="$cmd -not -name $1"  # add to not match
    shift                     # and remove from list of arguments
done
cmd="$cmd -exec rm -i {} ;"   # finally execute rm on the remaining matches

echo $cmd  # Print the final find command
$cmd       # And execute it

각 파일을 삭제하기 전에 묻도록 -i추가 했습니다 . rm하지만 물론 조정할 수 있습니다.

답변2

  1. 동일한 메커니즘란케이오답변, 그러나 변수가 없는 최소한의 방법으로POSIX쉘 기능:

    rmexcept(){ find "$1" $(shift; printf " -not -name %s" ${@}) -exec rm '{}' \; ;}
    

    쉘 명령은 또는 루프 printf대신 주요 작업을 수행합니다 .forwhile

  2. bash쉘을 사용하면 shift이는 매개변수 확장으로 대체될 수 있습니다.

    rmexcept(){ find "$1" $(printf " -not -name %s" ${@:2}) -exec rm '{}' \; ;}
    

find결과나 rm명령이 반환된 숫자보다 길면 두 함수 모두 작업을 완료하지 않습니다 getconf ARG_MAX. 바라보다:Bash 명령줄 및 입력 제한 사항.

관련 정보