別のディレクトリのファイル名に基づいてディレクトリのファイル名を変更する

別のディレクトリのファイル名に基づいてディレクトリのファイル名を変更する

ここで誰かがこの質問をしたかどうかはわかりませんが、私の質問です。名前が次のファイルがありますdir1

File 1.mp4
File 2.mp4
etc..

これで、ディレクトリにdir2次のエントリがあります。

Sub 1.srt
Sub 2.srt
etc..

Sub 1.srtになるように名前を変更するにはどうすればよいですかFile 1.srt?したがって、デフォルトでは*.srtすべてのファイルの名前をファイル名に変更します*.mp4。両方のディレクトリのファイル数は同じで、使用するprintf %s\\n *ファイルがソートされます。

答え1

両方のディレクトリには同じ数のファイルが含まれているため、両方の配列にファイル名を保存してから、配列インデックスのリストから各インデックスの名前を変更する方法があります(両方の配列の長さが同じであるため)。

mp4paths=(dir1/*.mp4)              # save mp4 file names in array
mp4names=("${mp4paths[@]##*/}")    # remove leading path components
name=("${mp4names[@]%.*}")         # remove extension
srt=(dir2/*.srt)                   # save srt file names in array
for i in "${!srt[@]}"              # for each index in the list of array indices 
do                                 # do stuff here...
mv "${srt[$i]}" dir2/"${name[$i]}".srt
done

これは、あらゆる種類のファイル名に適用されます。
「模擬実行」の場合mvに置き換えますprintf '%s -> %s\n'

答え2

paste -d=  <(ls dir2/*.srt)  <(ls dir1/*.mp4) | 
  perl -nlE 's/=dir1(.*).mp4/" "dir2$1.srt/; say("mv \"",$_, "\"")'  |
  bash
  • 最初の行は次の行を生成しますdir2/sub 1.srt=dir1/file 1.mp4
  • 2行目は次のように変更されます。mv "dir2/sub 1.srt" "dir2/file 1.srt"
  • 3行目は次の行を実行します。

答え3

これらのファイルが次の場合になる可能性があるとします。いいえ文字通り「File 1.mp4」と「Sub 1.srt」という名前が指定されている場合(それでもスクリプトは機能しますが)、2つのファイルセットの数字は次のようになります。

#! /bin/sh

dir1='./dir1'
dir2='./dir2'

find "$dir1" -maxdepth 1 -name '*.mp4' | while IFS= read f ; do
    num=$(echo "$f" | sed -e 's/^.* \([0-9]\+\)\.mp4/\1/')
    subtitle=$(find "$dir2" -maxdepth 1 -name "* $num.srt" | head -1)
    if [ -n "$subtitle" ] ; then
        bn=$(basename "$f" .mp4)
        mv "$subtitle" "$dir2/$bn.srt"
    fi
done

注:これは、名前に改行を含むファイルを除くすべてのファイルに適用されます。これはhead -1、同じ番号の.srtファイルが複数ある場合にスクリプトが失敗するのを防ぐためです。この場合、最初に見つかったファイルの名前が変更され、残りのファイルは無視されます。

字幕を.mp4ファイルと同じディレクトリに移動するには、行を次のmvように変更します。

mv "$subtitle" "$dir1/$bn.srt"

関連情報