문제
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에 의해 이미 수행되기 때문에 쉘 스크립트에서 루프를 생성하지 않습니다.