Bash скрипт для обмена местами файлов, файлы с одинаковыми именами - PullRequest
1 голос
/ 26 марта 2020

У меня есть куча .mov видео в папке на моей маме c:

Documents/MyMovs
├── SubFolder01
│   ├── SubSubFolder01
│   │   ├── MyFile1.mov
│   │   ├── MyPdf.pdf
│   │   └── MyTxt.txt
│   └── SubSubFolder02
│       ├── MyFile2.mov
│       ├── MyPdf.pdf
│       └── MyTxt.txt
etc.

Используя HandBrake, я конвертировал их в .mp4, но HandBrake поместил их в Movies / * 1004. *

Movies
├── MyFile1.mp4
├── MyFile2.mp4
etc.

Что я хочу сделать, это обменяться файлами и получить точную обратную ситуацию, когда все мои mp4 хранятся (в правильном месте) в Documents / MyMovs, а все файлы mov находятся в Movies / где я буду возможность в конечном итоге удалить их.

в конце я хочу:

Documents/MyMovs
    ├── SubFolder01
    │   ├── SubSubFolder01
    │   │   ├── MyFile1.mp4
    │   │   ├── MyPdf.pdf
    │   │   └── MyTxt.txt
    │   └── SubSubFolder02
    │       ├── MyFile2.mp4
    │       ├── MyPdf.pdf
    │       └── MyTxt.txt
    etc.

и

  Movies
    ├── MyFile1.mov
    ├── MyFile2.mov
    etc.

Я разработал следующий скрипт bash, чтобы помочь мне (хотя у меня есть время сделать это вручную из-за кризиса с коронавирусом):

#!/usr/local/bin/bash

MOV_DIR=$1
MP4_DIR=$2

declare -A FILES=( )

find $MOV_DIR -maxdepth 3 -name '*.mov' -print0 |
    while IFS= read -r -d '' line; do
        filename=$(basename "$line")
        extension="${filename##*.}"
        filename="${filename%.*}"
        path_to_file=$(dirname "$line")
        if [[ ! -v FILES[$filename] ]]; then
          FILES[$filename]="$path_to_file"
          #echo $FILES[$filename] prints something!
        fi
    done

#for k in "${!FILES[@]}"; do echo "$k - ${FILES[$k]}"; done  ## prints nothing!

find $MP4_DIR -maxdepth 3 -name '*.mp4' -print0 |
    while IFS= read -r -d '' line; do
        filename=$(basename "$line")
        extension="${filename##*.}"
        filename="${filename%.*}"
        path_to_file=$(dirname "$line")
        if [[ ! -z ${FILES["$filename"]} ]]; then
            mv "$path_to_file/$filename.mp4" "${FILES[$filename]}"
            mv "${FILES[$filename]}/filename.mov" "$path_to_file"
            #I would like to remove $filename from FILES as well but I don't know how
        fi
    done

Предположим, что все имена файлов уникальны и отличаются друг от друга для простоты.

Я положил все мои файлы MOV в имени файла карты -> path_to_filename; например, MyFile1 -> Documents / MyMovs / SubFolder01 / SubSubFolder01. Это первый блок поиска.

Во-вторых, я нахожу все мои файлы mp4 и получаю правильное местоположение, используя карту.

Код не работает, кажется, карта является локальной для первого поиска команда и не существует после. Кто-нибудь знает почему? Я использую bash версию 5.0.16 (1) -релиз. Спасибо всем!

PS: у вас есть совершенно другое, но лучшее решение, не стесняйтесь поделиться

1 Ответ

1 голос
/ 26 марта 2020

Если у вас есть один файл, найдите другой

find Documents -maxdepth 4 -mindepth 3 -name '*.mov' -print0 |
while IFS= read -r -d '' mov; do
        # extract the filename without extension
        name=$(basename "$mov" .mov)
        # find exactly the same name in Movies but with mp4
        mp4="Movies/$name.mp4"
        if [[ ! -f "$mp4" ]]; then
                echo "ERROR: File $mp4 does not exists" >&2
                exit 2
        fi
        # switch mp4 with mov
        movdir=$(dirname "$mov")
        mp4dir=$(dirname "$mp4")
        echo mv -v "$mp4" "$movdir"
        echo mv -v "$mov" "$mp4dir"
done

со следующим каталогом / воссозданием файла:

# find -type f
./Documents/MyMovs/Subfolder01/SubSubFolder01/MyFile1.mov
./Documents/MyMovs/Subfolder01/SubSubFolder02/MyFile2.mov
./Movies/MyFile1.mp4
./Movies/MyFile2.mp4

вывод:

mv -v Movies/MyFile1.mp4 Documents/MyMovs/Subfolder01/SubSubFolder01
mv -v Documents/MyMovs/Subfolder01/SubSubFolder01/MyFile1.mov Movies
mv -v Movies/MyFile2.mp4 Documents/MyMovs/Subfolder01/SubSubFolder02
mv -v Documents/MyMovs/Subfolder01/SubSubFolder02/MyFile2.mov Movies

не существует после. Кто-нибудь знает почему?

Потому что правая часть | запускается в подоболочке. Родительская оболочка ничего не знает о дочерней оболочке.

$ echo | { a=1; echo a=$a; }
a=1
$ echo a=$a
a=
...