주어진 범위에서 번호가 매겨진 파일을 어떻게 삭제합니까?


16

내가 가진 folderA그 숫자 순서로 시작하는 일부 파일이 a_000000. 내가하고 싶은 것은 특정 번호에서 시작하는 파일을 삭제하는 것입니다 . a_000750이 파일의 끝까지 말합시다 folderA. 쉘 스크립트를 사용 하여이 작업을 수행하는 방법을 알려주시겠습니까?


모든 파일 이름에 6 자리 접미사가 있다고 가정 할 수 있습니까?
muru

그렇습니다. :) a_000000부터 시작하여 숫자까지
Tak

5
rm a_000[89]* a_0007[5-9]*?
Rinzwind

@Rinzwind이 명령을 설명해 주시겠습니까?

2
@ user1460166을 a_000[89]*가진 모든 파일의 시작 부분을 포함 a_0008하거나 a_0009, 그리고 a_0007[5-9]*시작으로 모든 파일을 포함 a_0007하고 아무것도이어서 5와 9 사이의 번호를 포함.
muru

답변:


35

범위의 끝을 알고 있거나 추측 할 수 있다고 가정하면 중괄호 확장을 사용할 수 있습니다 .

rm a_{000750..000850}

위의 내용은 a_000750과 a_000850 사이의 101 개 파일을 삭제하며 존재하지 않는 파일을 참조하는 파일 이름에 대해 불평합니다. 파일이 너무 많으면 find다음을 사용하십시오 .

find . -name 'a_*' | while read file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

여기에 find단순히 일치하는 모든 파일이 나열됩니다 a_*. 목록은 while각 파일 이름을 변수로 읽는 루프로 전달됩니다 $file. 그런 다음 배쉬의 사용 문자열 조작하면 숫자 부분 (로 인쇄 파일을 찾을 경우, 기능 ./file, 그래서 ${file#./a_}수만 인쇄) 인 000750파일을 삭제, 이상. 은 -v그래서 당신이 제거 된 어떤 파일을 볼 수있는 단지가있다.

위의 파일 이름은 제정신입니다. 이름에 공백, 줄 바꿈 또는 기타 이상한 문자가있을 수있는 경우 대신 다음을 사용하십시오.

find . -name 'a_*' -print0 | while IFS= read -rd '' file; do 
  [ "${file#./a_}" -gt 000749 ] && rm -v "$file" 
done

왜 피해야 [[합니까?
muru

1
@muru 왜 그것을 사용합니까? 예를 들어 [[여기 [[ "${file#./a_}" > 000749 ]]를 단순화 하지 않고 더 짧게 만들지 않습니다. 나는 불필요한 구문을 사용하는 것을 좋아하지 않으며이 같은 간단한 쉘에서도 작동 dash합니다.
terdon

[[공백과 이상을 더 잘 처리 하기 때문에 (나는별로 신경 쓰지 않습니다 >).
muru

1
@muru 예,하지만 [변수를 인용하면 훨씬 더 많은 쉘에서 작동하며 더 간단합니다.
terdon

당신이 주장하는 경우. 내 문제가 아닙니다.
muru

3

다음과 같이 할 수 있습니다.

find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;

또는:

find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo

첫 번째 방법은 고정 접두사를 가정하고 제거하고 값을 확인합니다.

두 번째 방법은 고정 길이 접미사 (및 공통 고정 접두사)를 가정하고 그 사실에 의존합니다. 그리고 사전에 사전에 201나오지만 이전 31에는 그렇지 않습니다 031.

echo명령 을 사용하여 이것을 테스트 하고 올바른 파일이 나열되면 rm대신 사용하십시오.


그들 중 아무도 작동하지 않습니다 : /
Tak

@ user1460166 아, 아마 정규식 일치 때문일 것입니다. 업데이트하겠습니다.
muru

그래도 작동이 안되는. btw, 파일은 .png :)
Tak

@ user1460166 어떻게 작동하지 않습니까?
muru

터미널을 열고 폴더로 cd 한 다음 줄을 복사하여 붙여 넣지 만 파일은 삭제되지 않습니다.
Tak

0

POSIX 쉘 솔루션

terdon의 첫 번째 솔루션bash및 의 속성 인 괄호 확장에 의존 ksh하지만 /bin/shUbuntu에서 심볼릭 링크 된 표준 셸에서는 사용할 수 없습니다 /bin/dash.

/bin/sh스크립트의 이식성에 의존해야하는 경우 일반적으로 두 가지 방법으로 접근 할 수 있습니다. 하나는 globbing을 통해 이루어집니다. 그냥 cd folderA거기에서 실행 rm a_*합니다. 다른 방법 while <CONDITION>;do ...done은 쉘 언어를 사용하여 C 대안 for 루프 대안을 구현하고 다음 과 같이 숫자를 형식화하는 것입니다 printf.

$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'

여기서는을 사용 echo합니다. 교체 echo "$filename"와 함께 rm ./"$filename"또는 rm -- "$filename"당신은 파일을 삭제 할 준비가되면. 또한 cd원하는 디렉토리로 이미 들어가면 수행해야합니다 .

(ab) awk 사용

AWK는 좋은 C는 같은 언어는 두 가지 방법으로 우리를 도울 수있는 (1) 우리가 파일 이름을 생성 할 수 있습니다를위한 루프를 통해 형식을 sprintf기능, (2)를 통해 말했다 파일을 삭제 system()우리 생성 된 파일 이름과 통과되는 명령 rm명령을 ~까지 /bin/sh:

awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'

파일 이름을 "생성"하는 이식 가능한 접근 방식의 아이디어로 계속해서 Perl에서 동일한 작업을 수행 할 수 있습니다.

perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'

0

간단하게

rm partialfilename* -f

귀하의 예에서 그것은

rm a_00075* -f

1
죄송 합니다만, 그 범위는 아닙니다. 모든 파일은 a_00075...
Fabby

1
*는 와일드 카드입니다. OP는 다양한 항목을 삭제하는 방법에 대한 답변을 찾고 있습니다. 예를 들어 파일 1 ~ 100이 있고 # 41에서 # 75를 삭제하려는 경우
Joshua Besneatte
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.