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는 버전 번호를 제거하기 위해 일련의 패키지 이름을 어떻게 바꿀 수 있습니까? 나는 모두 주위 놀겠다는 거 봤는데 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
공백이있는 파일 이름에는 따옴표가 필요합니다.
rename "s/-[0-9.]*//" *.pkg
모든 파일이 동일한 디렉토리에 있으면 시퀀스
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
에가 있습니다 나오지 순서를 그룹화 정규 표현식은 앞에 백 슬래시 브라켓입니다, \(
그리고 \)
오히려 하나의 브라켓보다, (
하고 )
.
ls
스크립트에서 사용하지 마십시오 . 첫 번째 다양성은 printf '%s\n' * | sed ...
창의력 으로 얻을 수 있으며 약간의 창의력으로 제거 할 수도 sed
있습니다. Bash 는 리터럴 쉘 메타 문자를 포함하는 파일 이름이있는 경우 유용 할 수 printf
있는 '%q'
형식 코드를 제공합니다 .
다음과 같이 할 것입니다.
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 패턴 규칙이이 스크립트에 적용되며 이러한 패턴은 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입니다. 약간의 연구가 필요하지만 노력할만한 가치가있는 정규식을 사용해야합니다.
for
및 sed
등 괜찮지 만, 그냥 사용에 더 빨리 더 간단하고 rename
자신은 종종이 일을 찾을 경우.
rename
명령 이있는 것은 아닙니다 . 또한 일부는 기능, 구문 및 / 또는 옵션이 다른 다른 rename
명령을 사용합니다. 이것은 rename
꽤 인기있는 Perl처럼 보입니다 . 그러나 대답은 이것을 정말로 명확히해야합니다.
이것은 가정에서 작동하는 것 같습니다
.pkg를 떼어 낸 다음-..
for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done
-e
. 예 sed -e 's/\.pkg//g' -e 's/-.*//g'
.
동일한 폴더에서 *.txt
이름을 바꿀 여러 파일이 있습니다 .sql
. 아래는 나를 위해 일했습니다.
for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done
이 답변에 감사드립니다. 나는 또한 어떤 종류의 문제가 있었다. .nzb.queued 파일을 .nzb 파일로 이동. 파일 이름에 공백과 기타 균열이 있었고 이것은 내 문제를 해결했습니다.
find . -type f -name "*.nzb.queued" |
sed -ne "s/^\(\(.*\).nzb.queued\)$/mv -v \"\1\" \"\2.nzb\"/p" |
sh
그것은 Diomidis Spinellis의 대답을 기반으로합니다.
정규식은 전체 파일 이름에 대해 하나의 그룹과 .nzb.queued 이전 부분에 대해 하나의 그룹을 만든 다음 셸 이동 명령을 만듭니다. 인용 된 문자열로. 이것은 이미 sed에 의해 수행되기 때문에 쉘 스크립트에서 루프를 생성하는 것을 방지합니다.
-n
같은 방식으로 옵션을 해석하지 않습니다 .