Execute comandos complexos no script bash

Execute comandos complexos no script bash

Estou tentando executar o seguinte comando dentro de um script bash:

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

E estou tentando algo como:

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

Que mais tarde é usado em uma função, onde desejo que o comando seja realmente executado.

Tentei diversas variações, mas sempre falha, qual é a abordagem correta aqui?

-editar-

Outras informações

Se eu tentar algo como

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

Parece que tenta executar o comando imediatamente, o que não é o que pretendo (quero armazenar o comando correto para execução posterior), mas obtém todos os valores corretos, ou seja, nada vazio.

-editar 2-

Tentei dividir os comandos o máximo possível, assim:

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

Mas dá 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

Responder1

Normalmente para perguntas como esta, a resposta é lerBashFAQ #50: "Estou tentando colocar um comando em uma variável, mas os casos complexos sempre falham!". Breve resumo: variáveis ​​são para dados, não para código executável, e tentar colocar código nelas traz todos os tipos de problemas.

Mas neste caso há outro fator crítico: você vai executar o comando via ssh, o que significa que ele será passado para o sistema remotocomo dadose analisado como um comando por um shell no computador remoto. Isto significa que é razoável armazenar o comando (como dados) em uma variável no script (no computador local).

Parece-me que o maior problema que você está tendo é que quando você usa crases ou $( )(e elas não estão entre aspas simples), o comando interno é executado imediatamente (no computador local) e sua saída é armazenada em a variável. Para evitar isso, você pode escapar dos caracteres relevantes ao definir a variável:

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

Observe que usei $( )em vez de crases, pois geralmente é o preferido. Parece-me que você confundiu aspas crases com aspas simples em alguns pontos; eles parecem semelhantes, mas têm efeitos completamente diferentes. $( )faz essencialmente a mesma coisa, mas não é visualmente ambíguo.

Além disso, presumo ${FOLDER}que seja uma variável no computador local, portanto, precisa ser expandida imediatamente (e adicionei aspas simples caso contenha espaços ou outros metacaracteres do shell); se for expandido pelo shell remoto, use \"\${FOLDER|/other_folder\". Na verdade, colocar aspas simples ${FOLDER}não funcionará se ele próprio contiver aspas simples. Há uma maneira de consertar isso, mas não me preocupei aqui.

Você também pode usar aspas simples na atribuição de variáveis, mas terá problemas com as aspas simples no awkcomando (não há uma maneira limpa de aninhar aspas simples em uma string entre aspas simples) e não há uma maneira limpa para expandir ${FOLDER}no computador local. Isso pode ser resolvido com citações mistas, mas é confuso.

Finalmente, ao usar a variável, você deve colocá-la entre aspas duplas:

ssh -t user@server "$RM_CMD"

... isso não deveria importar neste caso específico, mas há todo tipo de coisa que pode dar errado com referências de variáveis ​​​​sem aspas duplas, portanto, geralmente é uma boa prática colocá-las com aspas duplas.

Responder2

Você pode verificar erros comuns em scripts bash comShellCheck, que funciona on-line, mas também está disponível como umprograma off-line. Ele suporta diferentes shells (identificados por shebang) e também fornece avisos de estilo (como no seu caso, para usar $(...)em vez de crases. Você também pode editar ao vivo seu código colado e ver como ele é classificado (útil em combinação com tutoriais normais sobre estilo de codificação ).

informação relacionada