Выполнение сложных команд в скрипте bash

Выполнение сложных команд в скрипте bash

Я пытаюсь выполнить следующую команду внутри скрипта bash:

rm -rf `ls -t ${FOLDER}/other_folder | awk 'NR>5'`

И я пробую что-то вроде:

RM_CMD="$(rm -rf 'ls -t ${FOLDER}/other_folder | awk NR>5')"

Которая позже используется в функции, где я хочу, чтобы команда действительно выполнялась.

Я пробовал несколько вариантов, но они всегда терпят неудачу. Каков правильный подход?

-редактировать-

Дальнейшая информация

Если я попробую что-то вроде

RM_CMD="rm -rf `ls -t ${FOLDER}/other_folder | awk 'NR>5'`"

Кажется, он пытается выполнить команду немедленно, что не соответствует моим намерениям (я хочу сохранить правильную команду для последующего выполнения), но он получает все правильные значения, т. е. ничего пустого.

-редактирование 2-

Я попытался максимально разделить команды, вот так:

LS_CMD="ls -t ${FOLDER}/other_folder"    
AWK_CMD="awk 'NR>5' ${LS_CMD}"    
RM_CMD="rm -rf '${AWK_CMD}'"

Но это создает следующую проблему:

+ ssh -t user@server 'rm -rf '\''awk '\''NR>5'\'' ls -t /full/path/to/folder/other_folder'\'''
bash: 5 ls -t /full/path/to/folder/other_folder: No such file or directory

решение1

Обычно на такие вопросы ответом будет прочитатьBashFAQ #50: «Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!». Краткое резюме: переменные предназначены для данных, а не для исполняемого кода, и попытка поместить в них код влечет за собой множество проблем.

Но в этом случае есть еще один критический фактор: вы собираетесь запустить команду через ssh, а это значит, что она будет передана удаленной системе.как данные, и анализируется как команда оболочкой на удаленном компьютере. Это означает, что разумно сохранить команду (как данные) в переменной в скрипте (на локальном компьютере).

Мне кажется, что самая большая проблема, с которой вы сталкиваетесь, заключается в том, что когда вы используете обратные кавычки или $( )(и они не в одинарных кавычках), команда внутри выполняется немедленно (на локальном компьютере), а ее вывод сохраняется в переменной. Чтобы избежать этого, вы можете экранировать соответствующие символы при определении переменной:

RM_CMD="rm -rf \$(ls -t '${FOLDER}/other_folder' | awk 'NR>5')"

Обратите внимание, что я использовал $( )вместо обратных кавычек, так как это обычно предпочтительнее. Мне кажется, что вы перепутали обратные кавычки с одинарными в некоторых местах; они выглядят похоже, но имеют совершенно разные эффекты. $( )делает по сути то же самое, но визуально не двусмысленно.

Также я предполагаю, ${FOLDER}что это переменная на локальном компьютере, поэтому ее нужно немедленно раскрыть (и я добавил одинарные кавычки вокруг нее на случай, если она содержит пробелы или другие метасимволы оболочки); если она должна быть раскрыта удаленной оболочкой, используйте \"\${FOLDER|/other_folder\"вместо этого. На самом деле, помещение одинарных кавычек вокруг ${FOLDER}не сработает, если она сама содержит одинарные кавычки. Есть способ исправить это, но я не стал заморачиваться.

Вы также можете использовать одинарные кавычки в назначении переменной, но тогда вы столкнетесь с проблемой одинарных кавычек в команде awk(нет чистого способа вкладывать одинарные кавычки в строку в одинарных кавычках) и нет чистого способа расширять ${FOLDER}на локальном компьютере. Это решается с помощью смешанных кавычек, но это грязно.

Наконец, при использовании переменной ее следует заключить в двойные кавычки:

ssh -t user@server "$RM_CMD"

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

решение2

Вы можете проверить распространенные ошибки в скриптах bash с помощьюShellCheck, который работает онлайн, но также доступен какоффлайн программа. Он поддерживает различные оболочки (определяемые shebang) и также выдает стилистические предупреждения (например, в вашем случае $(...)вместо обратных кавычек). Вы также можете редактировать вставленный код в реальном времени и смотреть, как он оценивается (полезно в сочетании с обычными руководствами по стилю кодирования).

Связанный контент