정규식과 일치하는 하위 디렉터리의 이름을 반복적으로 바꿉니다.

정규식과 일치하는 하위 디렉터리의 이름을 반복적으로 바꿉니다.

이라는 폴더가 있는 미디어 서버가 있습니다 Series. ( /media/Expansion2/Series/)

거기에는 (놀랍게도!) TV 시리즈가 있습니다. 이는 단지 프로그램 이름일 뿐입니다./media/Expansion2/Series/The Big Bang Theory/

각 쇼의 폴더 내에(그게 문제입니다) 시즌 폴더가 있습니다. 나는 현재 다음 두 가지 규칙(그리고 아마도 다른 규칙)을 혼합하여 사용하고 있습니다.

  1. /media/Expansion2/Series/The Big Bang Theory/The Big Bang Theory Season 1
  2. /media/Expansion2/Series/The Big Bang Theory/Season 2

마지막으로 모든 폴더의 이름을 Season #.

정규식으로 다음과 같이 말할 수 있습니다.s/.*(Season \d)/$1

파일이 아닌 폴더에서만 작동합니다. 또한 이는 약 50개 이상의 디스플레이 하위 폴더에 대해 작동하므로 /media/Expansion2/Series/해당 수준에서 시작하여 각 시리즈를 살펴봐야 합니다. :)

답변1

Debian 및 그 파생 제품(Ubuntu 포함):

find /media/Expansion2/Series/ -type d -exec rename -n 's/.*(Season \d)/$1/' {} ";"

rename명령은 Perl 패키지의 일부입니다. 다른 배포판에서는 표준 Linux 명령 외에는 제공하지 않지만 rename여기서는 유용하지 않습니다.

(-not true)가 수행하려는 작업을 표시 하고 rename -n문제가 되지 않으면 -n을 생략하고 그대로 두십시오.

답변2

다음 코드 조각은 Season [0-9]각 디스플레이 디렉토리에서 마지막으로 발생하기 전에 발생한 모든 항목을 삭제합니다 /media/Expansion2/Series. 정규식은 필요하지 않으며 그냥 glob입니다.

cd /media/Expansion2/Series
for show in ./*/; do
    (
        cd "$show" || { echo "cd failed.  Skipping $show"; exit 1; }
        for season in ./*Season\ [[:digit:]]*/; do
                season_prefix=${season%Season [[:digit:]]*}
                mv "$season" ./"${season#$season_prefix}"
        done
    )
done

답변3

안전을 유지하려면 이름을 다음 some show/some show stuff으로 바꾸십시오 some show/stuff.

for d in */; do
  for f in "$d${d%/} *"; do
    mv "$f" "${d}${f%$d${d%/} }"
  done
done

이전에 모든 것을 삭제하려면 다음을 수행하십시오 Season.

for x in */*Season*; do
  mv "$x" "${x%/*}/${x##*Season}Season"
done

${var#PATTERN}선행 PATTERN을 제거 $var하고 결과를 반환합니다. ${var%PATTERN}마지막으로 같은 일을하십시오. 가장 짧은 일치 항목의 접두어와 접미어를 ${var#PATTERN}각각 제거 하고 가장 긴 일치 항목을 삭제합니다.${var%PATTERN}${var##PATTERN}${var%%PATTERN}

답변4

두 가지 솔루션을 더 게시하겠습니다. 나중에 도움이 되기를 바랍니다. 이는 직장의 Linux 관리자가 제공한 것입니다. 이 못에 얼마나 많은 망치가 닿을 수 있는지 보여드리겠습니다!

해결 방법 1:

안녕하세요, 덴햄 님,

여기서는 "XXX Season #"이 있는 디렉터리 부분이 항상 "외부" 디렉터리(리프 노드)가 될 것이라는 몇 가지 가정을 해야 합니다.

어쨌든, 나는 작은 대본을 쓸 것이다. 다음과 같이 작동해야 합니다(디렉토리의 모든 공백이 캡처되도록 변수를 큰따옴표로 묶어야 합니다).

find /media/Expansion2/Series/ -type d | while read olddir
do 
   newdir=`echo "${olddir}" | awk -F "/" '$NF ~ /Season/ { last=substr($NF,index($NF, "Season")); while (i<(NF-1)) { i++; printf("/%s", $i) }; printf("/%s\n", last) } $NF !~ /Season/ { print }'`
   if [ "${olddir}" != "${newdir}" ]
   then
       mv "${olddir}" "${newdir}"
   fi
done

물론 " mv "${olddir}" "${newdir}" " 명령을 실행하기 전에 " echo "${olddir}" "${newdir}" 같은 것을 입력하여 예상한 결과가 나오는지 확인해야 합니다. 그렇지 않으면 또 다른 두통이 생길 수 있습니다 :-P


해결 방법 2:

안녕하세요, 덴햄 님,

대부분의 답변은 이미 질문에 나와 있습니다. 어쨌든 Series 폴더에서 다음과 같은 것을 실행하면 정상적으로 작동합니다.

find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "`dirname "$dir"`/`basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i"`"; done  


지침:
• find -minlength 2 -max깊이 2 -type d(디렉터리를 두 수준 아래로 나열)
• while read dir;(각 디렉토리에 대해 루프)
• mv -T "$dir"(소스 디렉토리를 ...로 이동) -T는 시즌 폴더가 고유하지 않은 경우 오류 22를 발생시킵니다. 즉, 동일한 디렉터리에 "The Big Bang Theory Season"과 "Season 22"가 없습니다.)
• dirname "$dir"은 path가 있는 디렉터리를 반환합니다.
• basename "$dir"은 디렉토리 이름을 반환합니다.
• sed "s/.시즌([0-9])$/Season \1/i" 는 만약을 대비해 대소문자를 구분하지 않는 정규식을 사용하여 마법을 수행합니다.

내 작은 테스트에서는 작동합니다 (mv 전에 echo를 먼저 사용해보십시오).

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/The Big Bang Theory Season 1
./The Big Bang Theory/The Big Bang Theory Season 1/file1.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file 3.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file2.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file
./The Big Bang Theory/The Big Bang Theory Season 1/3.avi
./Other Series
./Other Series/Season 2
./Other Series/Stre dsfdf sd dSeason 3

someuser@linux-box:/tmp/Series$ find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "dirname "$dir"/basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i""; done
mv: ./The Big Bang Theory/Season 2' and./The Big Bang Theory/Season 2' are the same file
mv: ./Other Series/Season 2' and./Other Series/Season 2' are the same file

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/Season 1
./The Big Bang Theory/Season 1/file1.avi
./The Big Bang Theory/Season 1/file 3.avi
./The Big Bang Theory/Season 1/file2.avi
./The Big Bang Theory/Season 1/file
./The Big Bang Theory/Season 1/3.avi
./Other Series
./Other Series/Season 3
./Other Series/Season 2

관련 정보