특정 문자열로 끝나는 모든 파일 삭제

특정 문자열로 끝나는 모든 파일 삭제

x 시퀀스가 ​​포함된 약 15,000개의 이미지가 있는 디렉토리가 있습니다.

scene1_000000.png
scene1_000001.png
scene1_000002.png
scene1_000003.png
scene1_000004.png
scene1_000005.png
scene1_000006.png
scene1_000007.png
scene1_000008.png
       .
       .
       .
       .
scene2_000300.png
scene2_000000.png
scene2_000001.png
scene2_000002.png
scene2_000003.png
scene2_000004.png
scene2_000005.png
scene2_000006.png
scene2_000007.png
scene2_000008.png
       .
       .
       .
       .
scene2_000300.png
       .
       .
       .
       .
scene50_000000.png
scene50_000001.png
scene50_000002.png
scene50_000003.png
scene50_000004.png
scene50_000005.png
scene50_000006.png
scene50_000007.png
scene50_000008.png
       .
       .
       .
       .
scene50_000300.png

각 시퀀스의 처음 150개 시퀀스를 유지하고 나머지는 삭제하고 싶습니다. 그래서 각 장면에 000000부터 000150까지의 시퀀스를 제공하겠습니다.

답변1

최신 버전의 bash에서는 중괄호 확장을 사용하여 이를 달성할 수 있습니다.

rm scene*_{000151..000300}.png

Bash의 중괄호 확장은 선행 0을 처리합니다.

$ echo {000000..000005}.png
000000.png 000001.png 000002.png 000003.png 000004.png 000005.png

따라서 이를 사용 {000151..000300}하여 필요한 파일 목록을 생성할 수 있습니다.

답변2

사용 find:

find . -maxdepth 1 -type f \
         -name 'scene*.png' \
       ! -name '*_0000[0-9][0-9].png' \
       ! -name '*_0001[0-4][0-9].png' \
       ! -name '*_000150.png' -print -delete

현재 디렉터리에서만 삭제하려는 모든 파일을 찾습니다.

다양한 -name플래그가 다음 작업을 수행합니다.

  1. 일치하는 항목만 선택하세요 scene*.png.
  2. 범위 내의 000000.png파일 이름을 필터링(선택 항목에서 제거)합니다 000099.png.
  3. 범위 내의 000100.png파일 이름을 필터링합니다 000149.png.
  4. 필터링하세요 000150.png.

...그런 다음 파일을 삭제합니다(여전히 고려 중인 경우). 이러한 파일(우리가 보관하려는 파일)이 삭제되는 것을 방지하기 위해 두 번째, 세 번째 및 네 번째 -name테스트는 무효화됩니다 .find

실제 삭제가 발생하기 전에 삭제된 파일의 이름도 인쇄됩니다.

먼저 삭제하고 실행하는 것이 좋습니다 -delete.

답변3

존재하다지쉬,<m-n>구문은 m과 n 사이의 숫자 문자열과 일치합니다. 둘 다 선택 사항입니다. 그러므로:

rm scene<->_<151->.png

scene*_(와일드카드로 시작할 수도 있지만 이렇게 하면 다른 패턴에 따라 이름이 지정된 파일이 있는 경우 <->예상치 못한 내용이 일치하는 것을 방지할 수 있습니다 .)*

답변4

약간의 스크립트일 수도 있습니다.

echo '#!/bin/bash
# Test argument
if [ $# = 1 ]; then
  if [ -d $1 ]; then
    cd $1
  else
    echo "$1 is not a directory" >&2
    exit 1
  fi
fi

declare f      # filname
declare -i fc  # file counter
declare -i fcs # file conter for a scene
declare sn     # scene number
declare csn    # current scene number
declare -i dfc # delete file counter
declare -i pfc # preserve file counter

# Open logfiles
exec file-delete>>&3
exec file-preserve>>&4

for f in *; do
  ((fc++))
  sn=${f#scene}
  sn=${sn%_*}
  if [ "$sn" = "$csn" ]; then
    ((fcs++))
  else
    # New number scene
    fcs=1   
    csn=$sn
    dfc=0
    pfc=0
    echo
  fi
  if ((fcs > 150));then
    # Candidate for deleting
    echo "$f" >>&3
    ((dfc++))
  else
    # Preserve file
    echo "$f" >>&4
    ((pfc++))
  fi
  # Display in console
  echo -en "\r scene $csn preserve:$pfc delete:$dfc"
done
echo

# Closing logfile
exec 3>&-
exec 4>&-

echo "Files scaned : $fc"
wc -l file-delete
wc -l file-preserve
' > ~/scanfile

실행하세요:

bash ~/scanfile [<pathdir>]

생략하면 현재 디렉터리에서 작동합니다.

아무것도 삭제하지 않고 스캔된 디렉터리에 두 개의 파일(삭제된 파일과 보관된 파일)을 씁니다.

확인한 후 다음 명령을 사용하여 삭제하려는 파일을 이동할 수 있습니다.

[cd <pathdir>]
mkdir tmp
while read; do mv -v $REPLY tmp; done < file-delete

결과가 좋다면

rm -rf tmp
rm file-delete file-preserve

관련 정보