web-dev-qa-db-ja.com

正規表現に一致するサブディレクトリの名前を再帰的に変更する

Seriesという名前のフォルダーを持つメディアサーバーがあります。 (_/media/Expansion2/Series/_)

その中で、私は(驚き!)TVシリーズを持っています。これらは単なるショー名です。例:_/media/Expansion2/Series/The Big Bang Theory/_

各ショーのフォルダー内(および問題がある場所です)にシーズンフォルダーがあります。私は現在、次の2つの規則が混在しています(おそらくいくつかの規則に加えて):

  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以上のshowサブフォルダ用であることにも言及する必要があるため、_/media/Expansion2/Series/_レベルで開始し、各シリーズを調べる必要があります:)

10
Denham Coote

Debianおよび派生物(Ubuntuを含む):

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

renameコマンドはPerlパッケージの一部です。他のディストリビューションでは提供されていません。代わりに、ここでは役に立たない標準のLinux renameコマンドを提供しています。

rename -n(実際にはそうではありません)は、実行したいことを表示します。問題はありません。-nを省略して実行します。

11
user unknown

安全にプレイしたい場合は、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}は、$varの先頭のPATTERNを取り除き、結果を返します。 ${var%PATTERN}は最後に同じことを行います。 ${var#PATTERN}および${var%PATTERN}は、一致する最短のプレフィックスとサフィックスをそれぞれ削除します。 ${var##PATTERN}および${var%%PATTERN}は、最長一致を削除します。

次のスニペットは、Season [0-9]の下にあるすべてのshowディレクトリで/media/Expansion2/Seriesが最後に発生する前に発生するすべてのものを取り除きます。正規表現は必要ありません。グロブだけです。

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
2
jw013

今後さらに役立つことを期待して、さらに2つの解決策を掲載します。これらは、職場の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 -mindepth 2 -maxdepth 2 -type d(ディレクトリを2レベル下にリスト)
•読み取り中。 (各ディレクトリでループ)
•mv -T "$ dir"(ソースディレクトリをに移動します...-シーズンフォルダーが一意でない場合、つまり「ビッグバン理論シーズン22」がない場合、エラーを取得するには-Tが必要です「と「シーズン22」は同じディレクトリにあります)
•dirname "$ dir"は、dirがあるパスを返します
•basename "$ dir"はディレクトリの名前を返します
•sed "s /.Season([0-9])$/Season\1/i"は、念のため、大文字と小文字を区別しない正規表現で魔法を完成させます。

私の小さなテストではうまくいきました(mvの前にエコーで最初に試してください):

_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" ";完了
mv:_./The Big Bang Theory/Season 2' and_./ビッグバン理論/シーズン2 'は同じファイルです
mv:_./Other Series/Season 2' and_./その他のシリーズ/シーズン2 'は同じファイルです</ code>

someuser @ linux-box:/ tmp/Series $ find

。/ビッグバン理論
./ビッグバン理論/シーズン2
./ビッグバン理論/シーズン2/file1.avi
./ビッグバン理論/シーズン2 /ファイル3.avi
./ビッグバン理論/シーズン2/file2.avi
./ビッグバン理論/シーズン2 /ファイル
./ビッグバン理論/シーズン2/3.avi
./ビッグバン理論/シーズン1
./ビッグバン理論/シーズン1/file1.avi
./ビッグバン理論/シーズン1 /ファイル3.avi
./ビッグバン理論/シーズン1/file2.avi
./ビッグバン理論/シーズン1 /ファイル
./ビッグバン理論/シーズン1/3.avi
./その他のシリーズ
./その他のシリーズ/シーズン3
./その他のシリーズ/シーズン2

0
Denham Coote