2014-11-18 1 views
1

Я использую оболочку bash на OS X (10.7). У меня есть довольно много каталогов аудио файлов, как так:Как сравнить (в сценарии оболочки) два файла по базовому имени, а затем отбросить один?

dir/audio.mp3 
dir/audio.m4a 

Я хотел бы программно отбросить один из файлов, но как? Я знаю, как получить базовые имена:

find . -type f -exec basename -a {} + | sort | awk -F"." '{print $1}' | uniq -d 

Но я в тупике, как «метка» в mp3s, скажем, так, что rm может делать свое дело. В идеале я бы сохранил файлы с наивысшим битрейтом, но на данный момент сокращается расширение файлов.

Возможно, Perl - лучший инструмент, но я недостаточно разбираюсь в Perl, чтобы начать заниматься этим.

+0

'basename' принимает только один файл за раз. Какой файл вы хотите отменить? Всегда ли это '.mp3', когда существуют' .mp3' и '.m4a'? Предположительно, если существует только один из двух возможных файлов с одним и тем же базовым именем, то вы хотите его сохранить. –

+0

Я бы построил что-то вроде 'find. -type f -name '* .m4a' | xargs script2delete_mp3_IfExists'. Где 'script2delete ...' просто выводит текстовые строки типа 'rm dir/audio.mp3', которые вы можете посмотреть перед выполнением. Когда все выходные данные выглядят хорошо, вы можете передать это, как 'find ... | xargs ... |/bin/bash', и оболочка затем выполнит команды, переданные через канал. Тогда вы можете сделать 'script2delete..' настолько умным, насколько хотите, если он найдет mp3, он может подтвердить, что' ..m4a' имеет более высокий битрейт, но если нет, вывод будет 'rm dir/audio.m4a'. Удачи. – shellter

+0

Джонатан, да, я бы всегда хотел отказаться от версии .mp3', но только если базовое имя дублируется с другим расширением. У меня также есть несколько файлов .flac, которые будут иметь приоритет. – sqldoug

ответ

3

В Perl то, что вам хотелось бы, это модуль File::Find.

#!/usr/bin/perl 

use strict; 
use warnings; 

use File::Find; 

my $search_path = "dir/"; 

my %exists; 

sub find_dupes { 
    my $filename = $_; 
    $filename =~ s/\.\w+$//; #remove extension) 
    if ($exists{$filename}) { 
     print $File::Find::name, " may be a duplicate of ", 
      $exists{$filename}, "($filename)\n"; 

     ##maybe delete the duplicate via unlink(); 
    } 
    else { 
     $exists{$filename} = $File::Find::name; 
    } 
} 

find(\&find_dupes, $search_path); 

NB: На самом деле не делается удаление. Это осталось для вас. Вы можете использовать File::Find, чтобы делать более умные сравнения, такие как время модификации, размер файла. Вы даже можете найти, что вы можете автоматически извлекать метаданные MP3 с помощью модуля, такого как MP3::Info. Я не использовал этот, поэтому YMMV.

+2

Спасибо, Собрике. Это ясно для меня, даже с моими рудиментарными навыками Перла. – sqldoug

+2

Просто потому, что у Perl есть плохая репутация за то, что он был уродливым кодом спагетти, это не значит, что вы _have_ следуете за трендом :) – Sobrique

+0

:) Круто узнать о 'MP3 :: Info', а также – sqldoug

1

Вы можете получить базовое имя файла с помощью команды basename (выглядит как вы делаете этот шаг от find в любом случае ...):

$ file="/foo/bar/baz.ext" 
$ echo $file 
/foo/bar/baz.ext 

$ name="$(basename "$file")" 
$ echo $name 
baz.ext 

Затем, чтобы удалить расширение, используйте %.*Параметр расширение раздеть последнюю точку, и все, что следует:

$ base="${name%.*}" 
$ echo $base 
baz 

man bash, поиск «Параметры расширения» для получения дополнительной информации. Это работает и в ksh/zsh.

+0

Расширение параметров, я все время забываю об этом. Благодарю. – sqldoug

+0

Также я думаю, что 'base =" $ {base%. *} "' Должно быть 'base =" $ {name%. *} "Здесь. – sqldoug

+0

@sqldoug это правильно, я изменил имя, чтобы добавить $ base и забыл его. Исправленный. –

Смежные вопросы