Вопрос Как удалить дублированные файлы на основе шаблона (см. Примеры ниже) с использованием сценария или команды Bash


Мой вопрос прост:

У меня есть видеофайлы, названные так:

  • xxxx_yyy_720_3800.mp4
  • xxxx_yyy_720_8000.mp4

где yyy может изменяться по длине (например, yyyyyy или более y)

Поскольку я не используюсь в сценариях оболочки, я хотел бы удалить автоматически (в указанной папке)

  • Если файл с именем xxx_yyy_720_3800.mp4 существует и если файл xxx_yyy_720_8000.mp4 существует, удалять xxx_yyy_720_3800.mp4
  • Если есть только файл xxx_yyy_720_8000.mp4 а также не файл xxx_yyy_720_3800.mp4, ничего не делать.

Любая помощь будет принята с благодарностью.


2
2017-07-14 16:22


происхождения


использовать fdups askubuntu.com/questions/177346/how-to-use-fdupes - Panther
Это только в xxxx_yyy_720_3800.mp4 количество y может варьироваться или это также xxxx_yyy_720_8000.mp4? Если да, то как эти вещи связаны (то есть, если любой файл соответствует xxxx_yyy_720_3800.mp4 быть удалены независимо от количества y в xxxx_yyy_720_8000.mp4)? - kos
число yyy может варьироваться от одного набора файлов к другому, но я хотел бы удалить файлы с тем же номером yyy, и если существует несколько файлов xxx_yyy_720_8000.mp4 и xxx_yyy_720_3800.mp4, необходимо удалить xxx_yyy_720_8000.mp4 - Laurent06000
Вопреки предложению использования fdupes, fslint или DupeGuru, мой вопрос заключается в сложном использовании этих инструментов - Laurent06000
Как я уже говорил, число yyy может меняться, но я хочу удалить xxx_yyyy_720_8000.mp4 только в том случае, если файл xxx_yyyy_720_3800.mp4 существует с тем же шаблоном yyyy. - Laurent06000


ответы:


С помощью find а также gawk

  1. устанавливать gawk

    sudo apt-get install gawk
    
  2. Зайдите в свою папку или замените . после find с вашим именем папки, например: find ~/my_video_duplicates f -iname …

  3. Проверить команду

    В приведенной ниже команде показаны только удаленные кандидаты

    find . -type f -iname "*_8000.mp4" -print0 | \
        while read -d $'\0' file; do \
            gawk -F_ '{ \
                a=gensub(/\_8000\./, "_3800.", "g" , $0); \
                system("if [ -f \""a"\" ]; then echo \""a"\" will be deleted; fi")}' <<< "$file";\
        done
    
  4. Проверьте снова, если вы находитесь в правильной папке или . после find с вашим именем папки, например: find ~/my_video_duplicates f -iname …

  5. Если вы уверены, выполните команду ниже

    find . -type f -iname "*_8000.mp4" -print0 | \
        while read -d $'\0' file; do \
            gawk -F_ '{ \
                a=gensub(/\_8000\./, "_3800.", "g" , $0); \
                system("if [ -f \""a"\" ]; then rm \""a"\"; fi")}' <<< "$file";\
        done
    

пример

  • Исходная ситуация

    % ls -og
    total 3
    -rw-rw-r-- 1 0 Jul 14 19:37 xxxx_yyy_720_3800.mp4
    -rw-rw-r-- 1 0 Jul 14 19:20 xxxx_yyy_720_8000.mp4
    -rw-rw-r-- 1 0 Jul 14 19:21 aaaa_yyy_720_8000.mp4
    
  • Сухой ход

    % find . -type f -iname "*_8000.mp4" -print0 | \
        while read -d $'\0' file; do \
            gawk -F_ '{ \
                a=gensub(/\_8000\./, "_3800.", "g" , $0); \
                system("if [ -f \""a"\" ]; then echo \""a"\" will be deleted; fi")}' <<< "$file";\
        done
    ./xxxx_yyy_720_3800.mp4 will be deleted
    
  • Удаление

    % find . -type f -iname "*_8000.mp4" -print0 | \
        while read -d $'\0' file; do \
            gawk -F_ '{ \
                a=gensub(/\_8000\./, "_3800.", "g" , $0); \
                system("if [ -f \""a"\" ]; then rm \""a"\"; fi")}' <<< "$file";\
        done
    
  • Окончательная ситуация

    % ls -og
    total 2
    -rw-rw-r-- 1 0 Jul 14 19:20 xxxx_yyy_720_8000.mp4
    -rw-rw-r-- 1 0 Jul 14 19:21 aaaa_yyy_720_8000.mp4
    

1
2017-07-14 17:36



Спасибо А.Б. но я попробовал первую из ваших команд (одну, чтобы эхо имя удаляемого файла) в тестовой папке, содержащей пару файлов xxxx_yyy_720_3800.mp4 и xxxx_yyy_720_8000.mp4, но это ничего не дает. Поскольку я не специалист по gawk, я не могу сказать, что не так - Laurent06000
Ничего или сообщение об ошибке? Можете ли вы отправить пример имен файлов? В моем сценарии я проверяю только часть 8000 - A.B.
Ничего не отображается (файл $ 0 будет удален, не отображается). Нет сообщения об ошибке. пример нескольких файлов xxx_yyyy_720_3800.mp4 и xxx_yyyy_720_8000.mp4 в той же тестовой папке. если yyyy варьируется от одного файла к другому, тогда файлы НЕ должны рассматриваться как «дубликаты», - Laurent06000
@ Laurent06000 Если ваше имя файла заканчивается*_8000.mp4 как описано в вашем вопросе, тогда отображается что-то. - A.B.
Извините за ошибку, но вот то, что я получаю в терминале в тестовой папке: find. -type f -iname "* _8000.mp4" -print0 | \> при чтении -d $ '\ 0' файла; do \> gawk -F_ '{\> a = gensub (/ \ _ 8000 \ ./, "_3800.", "g", $ 0); \> system ("if [-f \" "a" \ "], тогда echo \" "a" \ "будет удален; fi")} '<<< "$ file"; \> done ./xxx_yyyy_720p_3800 .mp4 будет удален laurent06000 @ PC-DE-LDP: ~ / Vidéos $ ./xxxx_yyyy_720_3800.mp4 будет удален с yyyy строго одинаково. Я попробую это жить на моем реальном forler. Большое спасибо. Laurent - Laurent06000


Используя Bash Оболочка

[ -f "file" ] проверяет, существует ли имя файла, и является обычным файлом (например, не каталогом или символической ссылкой)

"${name/%x/y}" заменяет суффикс x из $name с y,

Поэтому для удаления xxx_yyy_720_3800.mp4 только если xxx_yyy_720_8000.mp4 существует, где xxx а также yyy одинаковы в каждом случае, for все *_*_720_3800.mp4  in текущий каталог:

for name in *_*_720_3800.mp4
do if [ -f "${name/%3800.mp4/8000.mp4}" ]
   then echo "$name"
   fi
done

Изменить echo в rm если вы уверены, что все в порядке.


1
2017-07-14 18:30



Спасибо, Мартин, но это решение не выглядит безопасным: имейте в виду, что только файлы с yyyy одинаковы между файлами xxx_yyyy_720_3800.mp4 и xxx_yyyy_720_8000.mp4, которые можно рассматривать как «дубликаты». - Laurent06000
Верно. foo_bar_720_3800.mp4 будет удаляться только в том случае, если foo_bar_720_8000.mp4 существует и foo_baz_720_3800.mp4 будет удаляться только в том случае, если foo_baz_720_8000.mp4 существует. Возможно, я смутил вас: "${name/%x/y}" replaces the suffix x of $name with y.  Это x =720_3800.mp4 и что y =720_8000.mp4  Каждое имя рассматривается отдельно. - Martin Thornton
Извините за ошибку, но ваш скрипт работает в тестовой папке. Я попробую жить в реальной папке. Большое спасибо. Laurent - Laurent06000