변수에 파일 이름 패턴이 있는 xargs rm 찾기

변수에 파일 이름 패턴이 있는 xargs rm 찾기

다음과 같은 명령:

find /directory -type f -name "*.txt" -print | xargs rm

디렉터리와 하위 디렉터리의 모든 파일을 삭제 .txt하면 됩니다. 그러나 find예를 들어 파일 확장자에 대한 변수나 배열을 만든 다음 을 배치하면

TXT=(*.txt)
for ii in ${TXT[@]}; do
  find /directory -type f -name $TXT -print | xargs rm
done

이 명령은 하위 디렉터리의 파일을 삭제하지 않습니다 .txt. 왜? 하위 디렉터리의 파일을 삭제하기 위해 두 번째 코드 부분을 어떻게 변경합니까?

PS: 파일 확장자가 여러 개 있어서 배열을 사용했습니다.

답변1

배열 할당,

TXT=(*.txt)

*.txt패턴과 일치하는 현재 디렉터리의 파일 이름 목록으로 패턴을 확장합니다 . 쉘은 할당 시 이를 수행합니다. 당신이 원하는 것이 아닌가요? 다음과 같은 find리터럴 문자열을 제공하려고 합니다 *.txt.

pattern='*.txt'
find /directory -type f -name "$pattern" -exec rm {} +

여기서도 이를 제거 xargs rm하고 rm바로 실행을 시작합니다 find. 대부분의 현재 구현은 비표준으로 대체 find될 수 있습니다 .-delete-exec rm {} +

pattern='*.txt'
find /directory -type f -name "$pattern" -delete

여기서는 단일 패턴만 다루기 때문에 루프가 필요하지 않습니다. 또한 "$pattern"호출 시 따옴표가 find중요합니다. 그렇지 않으면 패턴이 시작하기 전에 현재 디렉터리에서 일치하는 모든 파일 이름으로 대체됩니다 find.

여러 모드의 경우 다음과 같은 루프를 수행할 수 있습니다.

patterns=( '*.txt' '*.tmp' )
for pattern in "${patterns[@]}"; do
    find /directory -type f -name "$pattern" -delete
done

배열 할당의 따옴표는 쉘이 패턴을 파일 이름 일치 패턴으로 사용하는 것을 방지하기 때문에 중요합니다. 같은 이유로 인용하는 "${patterns[@]}"것도 똑같이 중요합니다."$pattern"

find또 다른 접근 방식은 여러 스키마가 있더라도 을 한 번만 호출하는 것입니다 . /directory디렉터리 계층 구조가 큰 경우 작업 속도가 크게 향상될 수 있습니다. 다음 코드는 일련의 -name테스트를 구축하여 find이를 수행합니다 .

patterns=( '*.txt' '*.tmp' )

name_tests=( )
for pattern in "${patterns[@]}"; do
    name_tests+=( -o -name "$pattern" )
done

# "${name_tests[@]:1}" removes the initial "-o", which shouldn't be there.
name_tests=( '(' "${name_tests[@]:1}" ')' )

find /directory -type f "${name_tests[@]}" -delete

위 스크립트에서 마지막에 실행되는 실제 명령은 다음과 같습니다.

find /directory -type f '(' -name '*.txt' -o -name '*.tmp' ')' -delete

...이렇게 하면 파일 이름 접미사가 붙은 모든 일반 파일이 삭제됩니다..txt 또는 .tmp디렉토리 안이나 아래의 어느 곳에서나 가능합니다 /directory.

관련 정보