Bash로 일괄 이름 바꾸기 파일 주위 놀겠다는 거 봤는데 expr와 %%아무 소용. 예

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

당신의 일을 할 것입니다. 나오지 명령의 시퀀스를 생성합니다 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

모든 파일이 현재 디렉토리에 있다고 가정합니다. 그렇지 않다면 위에서 Javier가 조언 한대로 find를 사용해보십시오.

편집 : 또한이 버전은 위의 다른 기능과 같이 bash 특정 기능을 사용하지 않으므로 더 많은 이식성을 얻을 수 있습니다.


답변

다음은 현재 허용되는 답변 과 거의 동일한 POSIX 입니다. 이것은 ${variable/substring/replacement}Bourne 호환 쉘에서 사용할 수 있는 Bash 전용 매개 변수 확장을 교환합니다 .

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

매개 변수 확장 ${variable%pattern}variable일치하는 접미사가 pattern제거 된 값을 생성합니다 . ( ${variable#pattern}접두사 제거 도 있습니다 .)

-[0-9.]*오해의 소지가 있지만 수락 된 답변에서 하위 패턴 을 유지했습니다 . 정규식이 아니라 glob 패턴입니다. 따라서 “대시 뒤에 0 개 이상의 숫자 또는 점이 표시됨”을 의미하지 않습니다. 대신, “대시, 숫자 또는 점, 그 뒤에 오는 것”을 의미합니다. “anything”은 가장 긴 것이 아니라 가능한 가장 짧은 일치입니다. (배쉬 제공 ##하고 %%오히려 짧은보다, 가장 긴 접두사 나 접미사를 트리밍.)


답변

sed* nix에서 사용할 수 있다고 가정 할 수 있지만 sed -nmv 명령 생성을 지원할 수 있을지 확신 할 수 없습니다 . ( 참고 : GNU 만이 작업을 sed수행합니다.)

그럼에도 불구하고 bash 내장 및 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 정규식 패턴에 대한 참고 사항

정규 sed 패턴 규칙이이 스크립트에 적용되며 이러한 패턴은 PCRE (Perl 호환 정규식)가 아닙니다.
플랫폼에 따라 sed -r또는 둘 중 하나를 사용하여 확장 정규식 구문을 sed 할 수 있습니다 sed -E.

man re_formatsed 기본 및 확장 정규식 패턴에 대한 전체 설명은 POSIX 준수 를 참조하십시오 .


답변

이름 바꾸기가 이런 종류의 작업에 사용하기에 훨씬 더 간단한 도구라는 것을 알았습니다. OSX 용 Homebrew에서 찾았습니다.

귀하의 예를 들면 다음과 같습니다.

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

정규 표현식을 파악하는 것은 연습으로 남겨집니다 (공백을 포함하는 파일 이름을 다루는 것처럼)