Bash: Как использовать переменную в качестве аргумента с несколькими наборами кавычек

У меня есть папка, заполненная mp3-файлами, и я хочу вырезать все фреймы id3 usertext (кроме replaygain) - этот код, который я написал, сделает это, но он будет проходить по каждому файлу для каждого найденного тега, чтобы удалить его. Это приводит к тому, что скрипт выполняет циклическое повторение каждого mp3-файла несколько раз для выполнения задачи, которую я хочу.

Вот код, который работает:

#!/usr/bin/env bash
userframes=`eyeD3 *.mp3 | grep UserTextFrame | grep -v replaygain | awk -F ":" '{print $3}' | sed 's/]//g' | sed -e 's/^[ \t]*//' | sed 's/\s*$//g' | sort | uniq`

SAVEIFS=$IFS
IFS=$'\n'
for f in $userframes; do
    eyeD3 --user-text-frame="$f:" *.mp3
done
IFS=$SAVEIFS

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

eyeD3 --user-text-frame="desc1:" --user-text-frame="desc2:" *.mp3

Но я не могу понять, как это сделать. Думаю, я подошел ближе, пытаясь создать список сразу с переключателями в переменной, но есть некоторые странные проблемы с экранированием символов, которые я не могу понять.

eyeD3 *.mp3 | grep UserTextFrame | grep -v replaygain | awk -F ":" '{print $3}' | sed 's/]//g' | sed -e 's/^[ \t]*//' | sed 's/\s*$//g' | sort | uniq | sed -e "s|'|"'\\\'"'|g" | awk '{print "--user-text-frame=\x27" $0 ":\x27"}' | sed ':a;N;$!ba;s/\n/ /g'

который создает такой список (я пробовал двойные кавычки вместо синглов и избегал двойных кавычек):

--user-text-frame='ALBUMARTISTSORT:' --user-text-frame='ASIN:' --user-text-frame='Album Artist Credit:' --user-text-frame='Artist Credit:' --user-text-frame='CATALOGNUMBER:' --user-text-frame='MusicBrainz Album Artist Id:' --user-text-frame='MusicBrainz Album Id:' --user-text-frame='MusicBrainz Album Release Country:' --user-text-frame='MusicBrainz Album Status:' --user-text-frame='MusicBrainz Album Type:' --user-text-frame='MusicBrainz Artist Id:' --user-text-frame='MusicBrainz Release Group Id:' --user-text-frame='Script:'

но я не могу успешно передать это как переменную в eyeD3 следующим образом:

frames=`eyeD3 *.mp3 | grep UserTextFrame | grep -v replaygain | awk -F ":" '{print $3}' | sed 's/]//g' | sed -e 's/^[ \t]*//' | sed 's/\s*$//g' | sort | uniq | sed -e "s|'|"'\\\'"'|g" | awk '{print "--user-text-frame=\x27" $0 ":\x27"}' | sed ':a;N;$!ba;s/\n/ /g'`

eyeD3 $frames *.mp3

Я либо получаю ошибку

"eyeD3: ошибка: нераспознанные аргументы: Кредит: 'Идентификатор исполнителя альбома:' Идентификатор альбома: 'Страна выпуска альбома:' Статус альбома: 'Тип альбома: Идентификатор исполнителя: Идентификатор группы выпуска:' 01 - Do The Joy.mp3 02 - Love.mp3 03 - так легка ее походка.mp3 04 - будь пчелой.mp3 05 - не хватает света дня.mp3 06 - тропическая болезнь.mp3 07 - небесный свет.mp3 08 - ночной охотник.mp3 09 - Sing Sang Sung.mp3 10 - Eat My Beat.mp3 11 - Вы можете рассказать об этом всем.mp3 12 - African Velvet.mp3"

Или, если я попытаюсь поиграть с кавычками, я добавлю больше дублирующих тегов поверх существующих, таких как

'tag
tag

где раньше

tag

Может быть, есть более простой способ сделать то, что я хочу?

РЕДАКТИРОВАТЬ:

Синтаксис команды eyeD3 по подсказке:

--user-text-frame DESC:TEXT
                    Set the value of a user text frame (i.e., TXXX). To
                    remove the frame, specify an empty value. e.g.,
                    --user-text-frame='SomeDesc:'

так в качестве примера:

eyeD3 --user-text-frame='ALBUMARTISTSORT:' *.mp3

следует удалить тег рамки пользовательского текста с описанием ALBUMARTISTSORT из всех mp3-файлов в этом каталоге

типичный выход из eyeD3 с одним файлом (ввод *mp3 просто производит несколько записей для всех mp3 в dir)

$ eyeD3 12\ -\ African\ Velvet.mp3 
12 - African Velvet.mp3 [ 6.82 MB ]
-------------------------------------------------------------------------------
Time: 03:51 MPEG1, Layer III    [ ~247 kb/s @ 44100 Hz - Joint stereo ]
-------------------------------------------------------------------------------
ID3 v2.3:
title: African Velvet
artist: Air
album: Love 2
recording date: 2009
track: 12       genre: Electronic (id 52)
disc: 1/1
BPM: 0
Publisher/label: Emi
Unique File ID: [http://musicbrainz.org] : c5981690-b9ef-45f4-a8ce-7696a75190fb
Comment: [Description: ] [Lang: eng]

Lyrics: [Description: ] [Lang: eng]

UserTextFrame: [Description: replaygain_album_gain]
-9.11 dB
UserTextFrame: [Description: replaygain_album_peak]
1.238762
UserTextFrame: [Description: replaygain_track_gain]
-7.69 dB
UserTextFrame: [Description: replaygain_track_peak]
1.026620
UserTextFrame: [Description: CATALOGNUMBER]
509999663960-3
UserTextFrame: [Description: Album Artist Credit]
Air
UserTextFrame: [Description: MusicBrainz Album Type]
album
UserTextFrame: [Description: MusicBrainz Album Artist Id]
cb67438a-7f50-4f2b-a6f1-2bb2729fd538
UserTextFrame: [Description: MusicBrainz Artist Id]
cb67438a-7f50-4f2b-a6f1-2bb2729fd538
UserTextFrame: [Description: Script]
Latn
UserTextFrame: [Description: ASIN]
B002G9TWQQ
UserTextFrame: [Description: Artist Credit]
Air
UserTextFrame: [Description: ALBUMARTISTSORT]
Air
UserTextFrame: [Description: MusicBrainz Release Group Id]
34961bd0-b55b-4e9c-97eb-99763419afc0
UserTextFrame: [Description: MusicBrainz Album Id]
7e445cb0-3df7-3c38-b318-d68713294ff8
UserTextFrame: [Description: MusicBrainz Album Status]
Official
UserTextFrame: [Description: MusicBrainz Album Release Country]
CA
-------------------------------------------------------------------------------

2 ответа

Пожалуйста, поставьте пару двойных кавычек вокруг вашей переменной

eyeD3 "$frames" *.mp3

Я бы использовал что-то вроде

regex='UserTextFrame: [Description: (.*)]'
eyeD3 *.mp3 | grep UserTextFrame | grep -v replaygain | while read; do
    [[ $REPLY =~ $regex ]] && echo "${BASH_REMATCH[1]}"
done | sort -u | while read frame; do
    eyeD3 --user-text-frame "$frame:" *.mp3 
done

Первые три этапа конвейера такие же, как у вас. Далее я использую простую while цикл и регулярное выражение совпадают для вывода текста, следующего за "Description", вплоть до закрывающей скобки. Вывод этого цикла while состоит из всех описаний по всем MP3. Это через sort -u чтобы устранить дубликаты, а затем подается в другой while цикл с удаляет каждый уникальный элемент из всех MP3.

Другие вопросы по тегам