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 -n
mv 명령 생성을 지원할 수 있을지 확신 할 수 없습니다 . ( 참고 : 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
.
상당히 작은 변경이므로 해당 기능을 포함하는 것이 좋습니다.
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 정규식 패턴에 대한 참고 사항
정규 sed 패턴 규칙이이 스크립트에 적용되며 이러한 패턴은 PCRE (Perl 호환 정규식)가 아닙니다.
플랫폼에 따라 sed -r
또는 둘 중 하나를 사용하여 확장 정규식 구문을 sed 할 수 있습니다 sed -E
.
man re_format
sed 기본 및 확장 정규식 패턴에 대한 전체 설명은 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
정규 표현식을 파악하는 것은 연습으로 남겨집니다 (공백을 포함하는 파일 이름을 다루는 것처럼)