Ejecute comandos complejos en un script bash

Ejecute comandos complejos en un script bash

Estoy intentando ejecutar el siguiente comando dentro de un script bash:

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

Y estoy intentando algo como:

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

Que luego se usa en una función, donde quiero que realmente se ejecute el comando.

Probé varias variaciones, pero siempre falla, ¿cuál es el enfoque correcto aquí?

-editar-

Más información

Si intento algo como

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

Parece intentar ejecutar el comando inmediatamente, que no es lo que pretendo (quiero almacenar el comando correcto para su posterior ejecución), pero obtiene todos los valores correctos, es decir, nada vacío.

-editar 2-

Intenté dividir los comandos tanto como fuera posible, así:

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

Pero da este problema:

+ 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

Respuesta1

Normalmente para preguntas como esta, la respuesta es leerBashFAQ #50: "¡Estoy intentando poner un comando en una variable, pero los casos complejos siempre fallan!". Breve resumen: las variables son para datos, no para código ejecutable, y tratar de poner código en ellas tiene todo tipo de problemas.

Pero en este caso hay otro factor crítico: vas a ejecutar el comando a través de ssh, lo que significa que se pasará al sistema remoto.como datosy analizado como un comando por un shell en la computadora remota. Esto significa que es razonable almacenar el comando (como datos) en una variable en el script (en la computadora local).

Me parece que el mayor problema que estás teniendo es que cuando usas comillas invertidas o $( )(y no están entre comillas simples), el comando interno se ejecuta inmediatamente (en la computadora local) y su salida se almacena en La variable. Para evitar esto, puede escapar los caracteres relevantes al definir la variable:

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

Tenga en cuenta que utilicé comillas $( )inversas en lugar de comillas, ya que generalmente es lo preferido. Me parece que has confundido las comillas invertidas con las comillas simples en algunos puntos; Se ven similares, pero tienen efectos completamente diferentes. $( )hace esencialmente lo mismo, pero no es visualmente ambiguo.

Además, supongo ${FOLDER}que es una variable en la computadora local, por lo que debe expandirse inmediatamente (y agregué comillas simples alrededor en caso de que contenga espacios u otros metacaracteres del shell); si va a ser expandido por el shell remoto, utilícelo \"\${FOLDER|/other_folder\"en su lugar. En realidad, poner comillas simples ${FOLDER}no funcionará si contiene comillas simples. Hay una manera de solucionar este problema, pero no me he molestado aquí.

También podría usar comillas simples en la asignación de variables, pero luego tendría problemas con las comillas simples en el awkcomando (no hay una manera clara de anidar comillas simples en una cadena entre comillas simples) y no hay una manera limpia para expandirse ${FOLDER}en la computadora local. Estos se pueden resolver con comillas mixtas, pero es complicado.

Finalmente, cuando uses la variable, debes encerrarla entre comillas dobles:

ssh -t user@server "$RM_CMD"

... esto no debería importar en este caso particular, pero hay todo tipo de cosas que pueden salir mal con las referencias variables sin comillas dobles, por lo que generalmente es una buena práctica ponerlas entre comillas dobles.

Respuesta2

Puede comprobar errores comunes en los scripts bash conShellCheck, que funciona en línea pero también está disponible comoprograma fuera de línea. Admite diferentes shells (identificados por shebang) y también brinda advertencias de estilo (como en su caso, usar $(...)en lugar de comillas invertidas. También puede editar en vivo su código pegado y ver cómo se califica (útil en combinación con tutoriales normales sobre estilo de codificación). ).

información relacionada