문제

Bash는 버전 번호를 제거하기 위해 일련의 패키지 이름을 어떻게 바꿀 수 있습니까? 나는 둘 다와 함께 놀았다 expr 그리고 %%, 아무 소용이 없습니다.

예 :

Xft2-2.1.13.pkg becomes Xft2.pkg

jasper-1.900.1.pkg becomes jasper.pkg

xorg-libXrandr-1.2.3.pkg becomes 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

이에 주목하십시오 sed 정규 표현 그룹화 시퀀스는 괄호가 뒤틀린 괄호입니다. \( 그리고 \), 단일 괄호가 아닌 ( 그리고 ).

나는 다음과 같은 일을 할 것이다 :

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

모든 파일이 현재 디렉토리에 있다고 가정합니다. 그렇지 않은 경우, 위의 조언대로 Javier가 찾으십시오.

편집하다: 또한이 버전은 위의 다른 기능과 마찬가지로 Bash 특정 기능을 사용하지 않으므로 더 많은 휴대 성으로 이어집니다.

여기에 거의 동등한 posix가 있습니다 현재 인정 된 답변. 이것은 배쉬 전용을 거래합니다 ${variable/substring/replacement} 모든 Bourne 호환 쉘에서 사용할 수있는 파라미터 확장.

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

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

나는 하위 패턴을 보관했다 -[0-9.]* 허용 된 대답에서 아마도 오해의 소지가있을 것입니다. 정규 표현이 아니라 글로벌 패턴입니다. 따라서 "대시 뒤에 0 이상 또는 더 많은 숫자 또는 도트"를 의미하지는 않습니다. 대신, "대시, 숫자 또는 점, 그 뒤에 무엇이든"를 의미합니다. "무엇이든"는 가장 짧은 경기가 아니라 가장 짧은 경기가 될 것입니다. (배쉬 제안 ## 그리고 %% 가장 짧은 접두사 또는 접두사를 다듬기 위해.)

더 나은 사용 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

정규 표현식을 알아내는 것은 운동으로 남겨진다 (공백을 포함하는 파일 이름을 다루는대로)

우리는 가정 할 수 있습니다 sed 모든 *nix에서 사용할 수 있지만 지원할 수는 없습니다. sed -n MV 명령을 생성합니다. (노트: GNU 만 sed 이렇게합니다.)

그럼에도 불구하고 Bash Buildins and 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.

상당히 작은 변화이므로 해당 기능을 포함시키는 것이 좋을 것입니다.

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

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 호환 정규식). 당신은 정규 표현 구문을 SED로 만들 수 있습니다. sed -r 또는 sed -E플랫폼에 따라.

POSIX 호환을 참조하십시오 man re_format SED 기본 및 확장 된 Regexp 패턴에 대한 완전한 설명.

이름 바꾸기는 이런 종류의 일에 사용하기에 훨씬 더 간단한 도구라는 것을 알았습니다. 나는 OSX를 위해 홈브류에서 그것을 발견했다

당신의 예를 위해 나는 다음과 같습니다.

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

'S'는 대체를 의미합니다. 양식은 s/searchpattern/servement/files_to_apply입니다. 약간의 연구가 필요하지만 노력할 가치가 있습니다.

이것은 그것을 가정하면 작동하는 것 같습니다

  • 모든 것은 $ 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.queued 파일 이동 .nzb 파일로 이동합니다. 그것은 파일 이름에 공간과 다른 cruft를 가지고 있었고 이것은 내 문제를 해결했습니다.

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

그것은 diomidis spinellis의 답변을 기반으로합니다.

REGEX는 전체 파일 이름에 대해 하나의 그룹을 생성하고 .nzb.queued 이전의 부분에 대한 그룹을 생성 한 다음 쉘 이동 명령을 만듭니다. 문자열이 인용되어 있습니다. 또한 SED에 의해 이미 수행되기 때문에 쉘 스크립트에서 루프를 생성하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top