I'm not sure if this has been asked here but here is my problem. I have files in lets say dir1 named:

File 1.mp4
File 2.mp4

Now on directory dir2, I have files named:

Sub 1.srt
Sub 2.srt

How would I be able to rename Sub 1.srt so it becomes File 1.srt. So basically renaming all *.srt files to have the name of *.mp4 files. There is the same amount of files on both directories and using printf %s\\n * files are sorted.

  • 1
    How can you know that Sub 1.srt should be named File 1.srt and not File 2.srt? Is there an index, alphabetical order or something like this to use as a criteria?
    – Kira
    Nov 21 '15 at 21:51
  • @Kira there is the same amount of files on both directories and using printf %s\n * files are sorted
    – holasz
    Nov 21 '15 at 21:54

Since both directories contain the same number of files, here's an approach that saves file names in two arrays and then does the rename for each index in the list of array indices (as both arrays have the same length) :

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

This should work with all kind of file names.
For a "dry-run" replace mv with printf '%s -> %s\n'.

paste -d=  <(ls dir2/*.srt)  <(ls dir1/*.mp4) | 
  perl -nlE 's/=dir1(.*).mp4/" "dir2$1.srt/; say("mv \"",$_, "\"")'  |
  • First line produces lines like dir2/sub 1.srt=dir1/file 1.mp4
  • second line changes them to mv "dir2/sub 1.srt" "dir2/file 1.srt"
  • third line executes thos lines
  • @don_crissti: sorry I temporary delete the answer, because I cut and paste a wrong version and the previous was dangereous...
    – JJoao
    Nov 21 '15 at 23:29

Assuming that the files probably aren't literally named 'File 1.mp4' and 'Sub 1.srt' (although the script still works if they are) but that the numbers in both sets of files match:

#! /bin/sh


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"

Note: this will work an all files except those with newlines in the filename. The head -1 is to prevent the script from failing if there happens to be more than one .srt file with the same number....in that situation, the first file found will be renamed, the other(s) ignored.

If you want the subtitles moved into the same directory as the .mp4 files, change the mv line to:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.