Вопрос или проблема
Я хочу видеть команду, напечатанную в консоли перед её выполнением. Например, у меня есть
exiftool_command="exiftool \
-Title=\"$title\" \
-Keywords=\"$tags\" \
-Comment=\"$summary\" \
-Subtitle=\"$subtitle\" \
-Microsoft:Subtitle=\"$subtitle\" \
-Microsoft:Category=\"$tags_semicolon_separated\" \
-overwrite_original \
\"$mp4_file\""
echo "$exiftool_command" # Чтобы я мог видеть выполняемую команду с её содержимым
eval "$exiftool_command" # Теперь eval и выполняем её
Но использование eval
будет, конечно, проблематичным, если в переменной $summary
есть кавычки, например. А если я использую одинарные кавычки, то внутри переменных не могут быть одинарные кавычки. Я хочу, чтобы переменные могли свободно использовать кавычки или одинарные кавычки, независимо от этого. Поэтому единственный способ, который у меня остаётся, это дублировать информацию таким образом:
exiftool_command="exiftool \
-Title=\"$title\" \
-Keywords=\"$tags\" \
-Comment=\"$summary\" \
-Subtitle=\"$subtitle\" \
-Microsoft:Subtitle=\"$subtitle\" \
-Microsoft:Category=\"$tags_semicolon_separated\" \
-overwrite_original \
\"$mp4_file\""
echo "$exiftool_command"
exiftool \
-Title="$title" \
-Keywords="$tags" \
-Comment="$summary" \
-Subtitle="$subtitle" \
-Microsoft:Subtitle="$subtitle" \
-Microsoft:Category="$tags_semicolon_separated" \
-overwrite_original \
"$mp4_file"
Существует ли лучший способ достичь этого или мне стоит придерживаться этого “дублированного” метода?
Ответ или решение
Для того чтобы эффективно выводить команду Bash перед её выполнением, при этом избегая дублирования и проблем с кавычками, можно воспользоваться функциями и массивами в Bash. Это позволит вам не только сохранить команду и передать переменные без необходимости дублирования, но и построить команду в виде массива, что даст возможность легко выводить её на экран, а затем выполнять.
Вот один из подходов к решению вашей задачи:
# Определим функцию для выполнения команды
execute_command() {
# Выводим команду перед выполнением
echo "+ $*"
# Выполняем команду
"$@"
}
# Объявляем массив для команды
exiftool_command=("exiftool" \
-Title="$title" \
-Keywords="$tags" \
-Comment="$summary" \
-Subtitle="$subtitle" \
-Microsoft:Subtitle="$subtitle" \
-Microsoft:Category="$tags_semicolon_separated" \
-overwrite_original \
"$mp4_file"
)
# Вызовем функцию для выполнения команды
execute_command "${exiftool_command[@]}"
Объяснение кода:
-
Функция
execute_command
: Эта функция принимает аргументы, выводит строку с командой перед её выполнением (для удобства вы можете изменить формат вывода) и затем выполняет команду, используя"$@"
, что гарантирует правильную интерпретацию аргументов. -
Массив
exiftool_command
: Команда создаётся в виде массива. Это позволяет избежать проблем с кавычками и гарантирует правильную обработку всех аргументов, даже если они содержат пробелы или специальные символы. -
Вызов функции: При помощи
"${exiftool_command[@]}"
мы передаём все элементы массива в функцию, что позволяет избежать использованияeval
, который может быть небезопасным и проблематичным.
Этот метод не только делает код более чистым и читаемым, но и защищает от потенциальных ошибок, связанных с неправильной обработкой переменных или кавычек.