source

Bash를 사용하여 파일 이름 일괄 변경

ittop 2023. 5. 12. 22:40
반응형

Bash를 사용하여 파일 이름 일괄 변경

Bash가 일련의 패키지 이름을 변경하여 버전 번호를 제거하려면 어떻게 해야 합니까?둘 다 가지고 놀았어요expr그리고.%%헛되이

예:

Xft2-2.1.13.pkg된다Xft2.pkg

jasper-1.900.1.pkg된다jasper.pkg

xorg-libXrandr-1.2.3.pkg된다xorg-libXrandr.pkg

bash의 매개 변수 확장 기능을 사용할 수 있습니다.

for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done

공백이 있는 파일 이름에는 따옴표가 필요합니다.

모든 파일이 동일한 디렉토리에 있는 경우 시퀀스

ls | 
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' | 
sh

당신의 일을 할 것입니다.sed 명령어일련의 mv 명령어를 생성한 다음 이 명령어를 셸에 연결할 수 있습니다.우선 추적 없이 파이프라인을 실행하는 것이 가장 좋습니다.| sh명령이 사용자가 원하는 것을 수행하는지 확인합니다.

여러 디렉터리를 반복하려면 다음과 같은 방법을 사용합니다.

find . -type f |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |
sh

정규식 그룹화 시퀀스는 백슬래시 앞에 괄호가 붙습니다.\(그리고.\)단일 대괄호가 아닌(그리고.).

다음과 같은 작업을 수행합니다.

for file in *.pkg ; do
    mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg
done

당신의 모든 파일이 현재 디렉토리에 있다고 가정합니다.그렇지 않은 경우 위의 하비에르가 조언한 대로 찾기를 사용합니다.

편집: 또한 이 버전은 위의 다른 버전과 같이 bash 관련 기능을 사용하지 않으므로 휴대성이 향상됩니다.

우리는 추측할 수 있습니다.sed모든 *nix에서 사용할 수 있지만 지원할지 확신할 수 없습니다.sed -nmv 명령을 생성합니다. (참고: GNU만 해당)sed이렇게 합니다.)

그럼에도 불구하고, bash builtins와 sed, 우리는 이것을 하기 위해 셸 함수를 빠르게 만들 수 있습니다.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

사용.

sedrename 's|\(.*\)\(-[0-9.]*\.pkg\)|\1\2|' *.pkg

before:

./Xft2-2.1.13.pkg
./jasper-1.900.1.pkg
./xorg-libXrandr-1.2.3.pkg

after:

./Xft2.pkg
./jasper.pkg
./xorg-libXrandr.pkg

대상 폴더 만들기:

부터mv초기 버전을 사용할 수 없는 대상 폴더를 자동으로 만들지 않습니다.sedrename.

이는 상당히 작은 변경사항이므로 다음과 같은 기능을 포함하면 좋습니다.

유틸리티 기능이 필요합니다.abspathbash에는 이 빌드가 없기 때문에 (또는 절대 경로).

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

새 폴더 구조를 포함하는 sed/rename 패턴에 대한 대상 폴더를 생성할 수 있습니다.

이렇게 하면 대상 폴더의 이름을 알 수 있습니다.이름을 변경할 때 대상 파일 이름에 사용해야 합니다.

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

다음은 전체 폴더 인식 스크립트입니다.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

물론 특정 대상 폴더가 없을 때도 작동합니다.

만약 우리가 모든 노래를 폴더에 넣고 싶다면,./Beethoven/우리는 할 수 있습니다.

사용.

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

보너스 라운드...

이 스크립트를 사용하여 폴더에서 단일 폴더로 파일 이동:

일치하는 모든 파일을 수집하여 현재 폴더에 배치하고 싶다고 가정하면 다음 작업을 수행할 수 있습니다.

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

sed regex 패턴에 대한 참고 사항

일반 sed 패턴 규칙이 이 스크립트에 적용되지만 이 패턴은 PCRE(Perl Compatible Regular Expressions)가 아닙니다.구문을 정규 표현 을 사용할 수 .sed -r또는sed -E플랫폼에 따라 다릅니다.

호환 POSIX 파일 man re_formatsed 기본 및 확장 regexp 패턴에 대한 완전한 설명을 참조하십시오.

다음은 현재 승인된 답변과 거의 동등한 POSIX입니다.이 옵션은 Bash 전용입니다.${variable/substring/replacement}Bourne 호환 셸에서 사용할 수 있는 파라미터 확장.

for i in ./*.pkg; do
    mv "$i" "${i%-[0-9.]*.pkg}.pkg"
done

expansion은 다음과 같습니다.${variable%pattern}가 창를니다합의 합니다.variable일하는접사용여하를사미치와 pattern제거된.(또한 있습니다.${variable#pattern}접두사를 제거합니다.)

하위 패턴을 유지했습니다.-[0-9.]*오해의 소지가 있음에도 불구하고 받아들여진 답변에서.이것은 정규식이 아니라 글로벌 패턴이므로 "0개 이상의 숫자 또는 점이 이어지는 대시"를 의미하지 않습니다.대신 "숫자나 점 다음에 오는 대시"를 의미합니다. 긴 것이 짧은될 (는 "무엇든이이" "가가일치" 될배것가이며아장긴것다닐입니가일치제안장은짧시▁(배▁the▁",이▁("thing)무▁will것다anyb제니입아닐▁be▁"▁possible안▁the▁match▁shortest▁the가ash시치일")##그리고.%%가장 짧은 접두사 또는 접미사가 아닌 가장 긴 접두사 또는 접미사를 트리밍합니다.)

이름을 바꾸는 것이 이런 종류의 일에 훨씬 더 간단한 도구라는 것을 알게 되었습니다.OSX용 홈브루에서 찾았습니다.

예를 들어 다음을 수행합니다.

rename 's/\d*?\.\d*?\.\d*?//' *.pkg

's'는 대용품을 의미합니다.양식은 s/searchPattern/replacement/files_to_apply입니다.이를 위해서는 정규식을 사용해야 하는데 공부가 조금 필요하지만 노력할 가치가 충분히 있습니다.

더나사용은을 더 잘 합니다.sed이에 대해 다음과 같은 것이 있습니다.

find . -type f -name "*.pkg" |
 sed -e 's/((.*)-[0-9.]*\.pkg)/\1 \2.pkg/g' |
 while read nameA nameB; do
    mv $nameA $nameB;
 done

정규식 설정은 연습으로 남습니다(공백이 포함된 파일 이름을 처리하는 경우와 마찬가지로).

이는 다음과 같이 가정할 때 효과가 있는 것으로 보입니다.

  • 모든 것이 $pkg으로 끝납니다.
  • 당신의 버전 #은 항상 "-"로 시작합니다.

.pkg을 벗기고, 벗깁니다.

for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done

나는 여러 명이 있었습니다.*.txt파일 을 변파경일할이로 .sql같은 폴더에 있습니다. 아래는 저를 위해 일했습니다.

for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done

답변 감사합니다.저도 약간의 문제가 있었습니다..nzb 이동 중.파일을 .nzb 파일로 큐에 넣습니다.파일 이름에 공백 및 기타 크래프트가 포함되어 있어 문제가 해결되었습니다.

find . -type f -name "*.nzb.queued" |
sed -ne "s/^\(\(.*\).nzb.queued\)$/mv -v \"\1\" \"\2.nzb\"/p" |
sh

그것은 디오미디스 스피넬리스의 대답에 기초를 두고 있습니다.

정규식은 전체 파일 이름에 대해 하나의 그룹을 생성하고 .nzb 앞에 있는 부품에 대해 하나의 그룹을 생성합니다.대기열에 넣은 다음 셸 이동 명령을 만듭니다.현을 따옴표로 묶어서요.이것은 또한 이미 sed에 의해 수행되었기 때문에 셸 스크립트에서 루프를 생성하는 것을 방지합니다.

언급URL : https://stackoverflow.com/questions/602706/batch-renaming-files-with-bash

반응형