Как эффективно вывести bash-команду на печать перед её выполнением?

Вопрос или проблема

Я хочу видеть команду, напечатанную в консоли перед её выполнением. Например, у меня есть

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[@]}"

Объяснение кода:

  1. Функция execute_command: Эта функция принимает аргументы, выводит строку с командой перед её выполнением (для удобства вы можете изменить формат вывода) и затем выполняет команду, используя "$@", что гарантирует правильную интерпретацию аргументов.

  2. Массив exiftool_command: Команда создаётся в виде массива. Это позволяет избежать проблем с кавычками и гарантирует правильную обработку всех аргументов, даже если они содержат пробелы или специальные символы.

  3. Вызов функции: При помощи "${exiftool_command[@]}" мы передаём все элементы массива в функцию, что позволяет избежать использования eval, который может быть небезопасным и проблематичным.

Этот метод не только делает код более чистым и читаемым, но и защищает от потенциальных ошибок, связанных с неправильной обработкой переменных или кавычек.

Оцените материал
Добавить комментарий

Капча загружается...