roshan
roshan

Reputation: 95

Move files to respective folders based on their file name

I am having a bit of problem in arranging my files

So I have around 3000 movies named as per below, in that there are multiple movies which are the same but are having different resolutions. Here is a sample:

Toy Story 4 (2019) - 720p h265 10 AAC 6ch.mkv
Toy Story 4 (2019) - 1080p h265 10 AAC 6ch.mkv
Toy Story 4 (2019) - 2160p h265 10 AAC 6ch.mkv
X Men Apocalypse (2016) - 1080p h265 10 AAC 8ch.mkv
X Men Apocalypse (2016) - 720p h265 10 AAC 8ch.mp4

What I would like to Have is to move all common movies to a common Folder. Like this

Toy Story 4 (2019)
  Toy Story 4 (2019) - 720p h265 10 AAC 6ch.mkv
  Toy Story 4 (2019) - 1080p h265 10 AAC 6ch.mkv
  Toy Story 4 (2019) - 2160p h265 10 AAC 6ch.mkv
X Men Apocalypse (2016)
  X Men Apocalypse (2016) - 1080p h265 10 AAC 8ch.mkv
  X Men Apocalypse (2016) - 720p h265 10 AAC 8ch.mp4

PS: All of my movies are named this way

I had a similar problem before, and it was solved - Here

#!/usr/bin/env bash

declare -A uniq

##: The script should be inside the directory where the video files are
for files in *; do
  if [[ $files =~ ^(.*[[:digit:]]{4})\.(.+)$ ]]; then
    no_space=${BASH_REMATCH[1]// /.}
    uniq[$no_space]=1
    all_files+=("${BASH_REMATCH[0]}")
    first_part+=("${BASH_REMATCH[1]}")
  fi
done

for j in "${!uniq[@]}"; do
  mkdir -p "$j"
  dir+=("$j")
done

for i in "${!all_files[@]}"; do
  for k in "${dir[@]}"; do
    if [[ ${first_part[$i]// /.} == $k ]]; then
      mv -v  "${all_files[$i]}" "$k"
    fi
  done
done

So I tried the same solution, unfortunately, it didn't work at all

I got this error

“$'\r': command not found”

Any help is deeply appreciated.

Ps: I also tried software like Tinymediamanager, but it could move only one movie, not all of them

Upvotes: 0

Views: 389

Answers (2)

Paul Hodges
Paul Hodges

Reputation: 15418

I'd suggest that unless you need the added complication for a reason, just keep it as simple as possible.

The code is slower and less efficient but a lot easier to read if you do them individually.

for f in *.mkv
do d="${f% - *}"
   mkdir -p "$d"
   mv "$f" "$d/"
done

If you want to speed it up -

for f in *.mkv
do [[ -e "$f" ]] || continue
   d="${f% - *}"
   mkdir -p "$d/"
   mv "$d"*.mkv "$d"
done

Does that not accomplish what you wanted?

Upvotes: 1

roshan
roshan

Reputation: 95

So I found the solution

In my previous post..one User had given me another bash script to use with any other instances..But when I ran it gave me error..because it was not in UNIX format..I used Notepad ++ to change the Format and alas!..it worked

Thank you everyone for your Suggestion and Thank you Jetchisel

Here is the Solution

#!/usr/bin/env bash

declare -A uniq

for files in *; do
  if [[ $files =~ ^(.*\(?[[:digit:]]{4}\)?)[\.[[:blank:]]]?(.+)$ ]]; then
    no_space=${BASH_REMATCH[1]// /.}
    uniq[$no_space]=1
    all_files+=("${BASH_REMATCH[0]}")
    first_part+=("${BASH_REMATCH[1]}")
  fi
done

for j in "${!uniq[@]}"; do
  mkdir -p "${j//[)(]}"
  dir+=("$j")
done

for i in "${!all_files[@]}"; do
  for k in "${dir[@]}"; do
  if [[ ${first_part[$i]// /.} == $k ]]; then
    mv -v  "${all_files[$i]}" "${k//[)(]}"
  fi
  done
done

Run this inside the Folder where your Files are

This is from Here

Upvotes: 0

Related Questions