변수에서 파일 이름 패턴이 있는 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. 왜? 하위 디렉터리의 파일을 삭제하기 위해 이 두 번째 코드를 변경하는 방법은 무엇입니까?

추신: 파일 확장자가 두 개 이상이므로 배열을 사용했습니다.

답변1

귀하의 배열 할당,

TXT=(*.txt)

*.txt해당 패턴과 일치하는 현재 디렉터리의 목록 파일 이름으로 패턴을 확장합니다 . 쉘은 할당 시 이 작업을 수행합니다. 이것은 당신이 원하는 것이 아닙니다. 다음과 같이 find리터럴 string 을 제공하려고 합니다 .*.txt

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

여기 에서는 을 제거하고 xargs rm대신 . 의 최신 구현에서는 다음 대신 비표준을 사용할 수 있습니다 .rmfindfind-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[@]}"and 를 인용하는 것도 마찬가지로 중요합니다."$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.

관련 정보