Programing

Bash로 일괄 이름 바꾸기 파일

crosscheck 2020. 8. 28. 06:51
반응형

Bash로 일괄 이름 바꾸기 파일


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이것에 대해 더 잘 사용하십시오 .

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 -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; }

Once we have that we can generate the target folder(s) for a sed/rename pattern which includes new folder structure.

This will ensure we know the names of our target folders. When we rename we'll need to use it on the target file name.

# 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"

Here's the full folder aware script...

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
}

Of course, it still works when we don't have specific target folders too.

If we wanted to put all the songs into a folder, ./Beethoven/ we can do this:

Usage

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

Bonus round...

Using this script to move files from folders into a single folder:

Assuming we wanted to gather up all the files matched, and place them in the current folder, we can do it:

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

Note on sed regex patterns

Regular sed pattern rules apply in this script, these patterns aren't PCRE (Perl Compatible Regular Expressions). You could have sed extended regular expression syntax, using either sed -r or sed -E depending on your platform.

See the POSIX compliant man re_format for a complete description of sed basic and extended regexp patterns.


I find that rename is a much more straightforward tool to use for this sort of thing. I found it on Homebrew for OSX

For your example I would do:

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

The 's' means substitute. The form is s/searchPattern/replacement/ files_to_apply. You need to use regex for this which takes a little study but it's well worth the effort.


This seems to work assuming that

  • everything ends with $pkg
  • your version #'s always start with a "-"

strip off the .pkg, then strip off -..

for x in $(ls); do echo $x $(echo $x | sed 's/\.pkg//g' | sed 's/-.*//g').pkg; done

I had multiple *.txt files to be renamed as .sql in same folder. below worked for me:

for i in \`ls *.txt | awk -F "." '{print $1}'\` ;do mv $i.txt $i.sql; done

Thank you for this answers. I also had some sort of problem. Moving .nzb.queued files to .nzb files. It had spaces and other cruft in the filenames and this solved my problem:

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

It is based on the answer of Diomidis Spinellis.

The regex creates one group for the whole filename, and one group for the part before .nzb.queued and then creates a shell move command. With the strings quoted. This also avoids creating a loop in shell script because this is already done by sed.

참고URL : https://stackoverflow.com/questions/602706/batch-renaming-files-with-bash

반응형