bash로 많은 수의 이미지 파일 이름 바꾸기 0089000로 이동 합니다 0163022.

대략 이름을 바꿔야합니다. 70,000 개 파일 예를 들면 :에서 sb_606_HBO_DPM_0089000sb_606_dpm_0089000

숫자 범위는에서 0089000로 이동 합니다 0163022. 이름의 첫 부분 만 변경하면됩니다. 모든 파일은 단일 디렉토리에 있으며 순차적으로 번호가 매겨집니다 (이미지 시퀀스). 숫자는 변경되지 않아야합니다.

내가 이것을 bash에서 시도하면 ‘인수 목록이 너무 길다’는 소리가 난다.

편집하다:

먼저 단일 파일의 이름을 바꾸려고했습니다 mv.

mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx

그런 다음 범위의 이름을 바꾸려고했습니다 (지난 주에 파일로드를 이동하는 방법을 배웠으므로 동일한 이름의 구문을 사용하여 파일 이름을 바꿀 수 있다고 생각했습니다 …). 나는 다음과 같은 것을 시도 했다고 생각한다 .

mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx


답변

한 가지 방법은 사용하는 것입니다 find함께 -exec하고 +옵션을 선택합니다. 이것은 인수 목록을 구성하지만, 최대 인수 목록을 초과하지 않고 모든 파일에서 작동하는 데 필요한만큼의 호출로 목록을 나눕니다. 모든 인수가 동일하게 취급 될 때 적합합니다. 이것은의 경우 rename로 생각하지 mv.

Perl 이름 바꾸기를 설치해야 할 수도 있습니다.

sudo apt install rename

그런 다음 예를 들어 사용할 수 있습니다.

find . -maxdepth 1 -exec rename -n 's/_HBO_DPM_/_dpm_/' {} +

-n실제로 파일 이름을 바꾸려면 테스트 후 제거하십시오 .


답변

세 가지 대안을 제안하겠습니다. 각각은 간단한 한 줄 명령이지만, 처리 할 파일이 동일한 직접 경로의 다른 파일과 혼합되는 경우를 대비하여보다 복잡한 경우에 대한 변형을 제공합니다.

mmv

동일한 이름
패키지 에서 mmv 명령 을 사용합니다 .

mmv '*HBO_DPM*' '#1dpm#2'

인수는 문자열로 전달되므로 셸에서 glob 확장이 발생하지 않습니다. 이 명령은 정확히 두 개의 인수를받은 다음 파일 수에 대한 제한없이 내부에서 해당 파일을 찾습니다. 또한 위의 명령은 첫 번째 glob과 일치하는 모든 파일의 이름이 바뀌어야한다고 가정합니다. 물론보다 구체적으로 설명 할 수 있습니다.

mmv 'sb_606_HBO_DPM_*' 'sb_606_dpm_#1'

동일한 디렉토리에 요청 된 번호 범위를 벗어난 파일이있는 경우이 답변에서 더 아래에 주어진 루프 오버 번호를 사용하는 것이 좋습니다. 그러나 적절한 패턴으로 일련의 mmv 호출을 사용할 수도 있습니다.

mmv 'sb_606_HBO_DPM_0089*'       'sb_606_dpm_0089#1'    # 0089000-0089999
mmv 'sb_606_HBO_DPM_009*'        'sb_606_dpm_009#1'     # 0090000-0099999
mmv 'sb_606_HBO_DPM_01[0-5]*'    'sb_606_dpm_01#1#2'    # 0100000-0159999
mmv 'sb_606_HBO_DPM_016[0-2]*'   'sb_606_dpm_016#1#2'   # 0160000-0162999
mmv 'sb_606_HBO_DPM_01630[01]?'  'sb_606_dpm_01630#1#2' # 0163000-0163019
mmv 'sb_606_HBO_DPM_016302[0-2]' 'sb_606_dpm_016302#1'  # 0163020-0163022

숫자를 반복하다

설치를 피하거나이 범위 밖의 일치를 피하면서 숫자 범위로 선택해야하고 74,023 명령 호출을 기다릴 준비가 되었다면 일반 bash 루프를 사용할 수 있습니다.

for i in {0089000..0163022}; do mv sb_606_HBO_DPM_$i sb_606_dpm_$i; done

시퀀스에 간격이 없기 때문에 이것은 특히 잘 작동합니다. 그렇지 않으면 소스 파일이 실제로 존재하는지 확인할 수 있습니다.

for i in {0089000..0163022}; do
  test -e sb_606_HBO_DPM_$i && mv sb_606_HBO_DPM_$i sb_606_dpm_$i
done

for ((i=89000; i<=163022; ++i))괄호 확장 과 달리 몇 년 전에 일부 Bash 릴리스 이후 선행 0을 처리합니다. 실제로 변경을 요청 했으므로 유스 케이스를 보게되어 기쁩니다.

추가 자료 : Bash 정보 페이지의 브레이스 확장 , 특히 관련 부분 {x..y[..incr]}.

파일을 반복

또 다른 옵션은 해당 정수 범위를 반복하는 대신 적절한 glob를 반복하는 것입니다. 이 같은:

for i in *HBO_DPM*; do mv "$i" "${i/HBO_DPM/dpm}"; done

이 역시 mv파일 당 한 번의 호출입니다. 그리고 루프는 요소의 긴 목록에 있지만 전체 목록은 하위 프로세스에 인수로 전달되지 않지만 bash에 의해 내부적으로 처리되므로 제한이 문제를 일으키지 않습니다.

추가 정보 : Bash 정보 페이지의 쉘 매개 변수 확장${parameter/pattern/string} .

숫자 범위를 제공 한 숫자 범위로 제한하려면 해당 검사를 추가 할 수 있습니다.

for i in sb_606_HBO_DPM_+([0-9]); do
  if [[ "${i##*_*(0)}" -ge 89000 ]] && [[ "${i##*_*(0)}" -le 163022 ]]; then
    mv "$i" "${i/HBO_DPM/dpm}"
  fi
done

여기에 ${i##pattern}가장 긴 접두사 일치 제거 pattern에서를 $i. 가장 긴 접두사는 무엇이든, 밑줄, 0 또는 그 이상의 0으로 정의됩니다. 후자는 설정 되는 옵션 에 따라 *(0)확장 된 glob 패턴 으로 작성됩니다 . 앞의 0을 제거하는 것은 숫자를 밑이 8이 아닌 밑이 10으로 취급하는 데 중요합니다. in 루프 인수는 파일이 동일하게 시작하지만 끝나지 않는 파일이있는 경우를 대비하여 하나 이상의 숫자와 일치하는 또 다른 확장 된 glob입니다. 번호.extglob+([0-9])


답변

ARG_MAX한계를 극복 하는 한 가지 방법 은 bash 쉘의 내장을 사용하는 것입니다 printf.

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'

전의.

rename -n 's/HBO_DPM/dpm/' sb_*
bash: /usr/bin/rename: Argument list too long

그러나

printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'
rename(sb_606_HBO_DPM_0089000, sb_606_dpm_0089000)
.
.
.
rename(sb_606_HBO_DPM_0163022, sb_606_dpm_0163022)

답변

find . -type f -exec bash -c 'echo $1 ${1/HBO_DPM/dpm}' _ {} \;
./sb_606_HBO_DPM_0089000 ./sb_606_dpm_0089000

find.모든 파일의 현재 디렉토리 에 있고 파일 을 하나씩 바꾸면서 -type f찾은 파일의 이름을 바꾸십시오.$1HBO_DPMdmp -exec ... \;

교체 echomv이름 변경을 수행 할 수 있습니다.


답변

다음과 같은 작은 파이썬 스크립트를 작성할 수 있습니다.

import os
for file in os.listdir("."):
    os.rename(file, file.replace("HBO_DPM", "dpm"))

파일이 들어 rename.py있는 폴더에서 와 같이 텍스트 파일로 저장 한 다음 해당 폴더의 터미널로 이동하십시오.

python rename.py

답변

파일별로 파일을 만들 수 있습니다 (시간이 걸릴 수 있음)

sudo apt install util-linux  # if you don't have it already
for i in *; do rename.ul HBO_DPM dpm "$i"; done

rename다른 답변에 사용 된 Perl과 마찬가지로 rename.ul옵션 -n또는 --no-act테스트가 있습니다.


답변

나는 나의 가장 친한 친구 sed를 파티에 초대 한 사람이 없다는 것을 안다 . :). 다음 for루프는 목표를 달성합니다.

for i in sb_606_HBO_DPM*; do
  mv "$i" "$(echo $i | sed 's/HBO_DPM/dpm/')";
done

이러한 작업을위한 많은 도구가 있으므로 가장 이해하기 쉬운 도구를 선택하십시오. 이것은 간단하고 쉽게이 또는 다른 목적에 맞게 변경됩니다 …