Executa comandos complexos no script bash

0

Estou tentando executar o seguinte comando em um script bash:

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

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 eu quero que o comando seja executado.

Eu tentei várias variações, mas sempre falha, qual é a abordagem correta aqui?

-edit -

Mais informações

Se eu tentar algo como

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

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

-edit 2 -

Eu 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 isso dá esse 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
    
por Thin_icE 30.09.2016 / 13:04

2 respostas

3

Normalmente, para perguntas como essa, a resposta é ler BashFAQ # 50: "Estou tentando colocar um comando em uma variável , mas os casos complexos sempre falham! ". Resumo: as variáveis são para dados, não para códigos executáveis, e tentar colocar códigos nelas tem 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 remoto como dados , e analisado como um comando por um shell no computador remoto. Isso 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 backquotes ou $( ) (e eles não estão entre aspas simples), o comando dentro é executado imediatamente (no computador local), e sua saída fica armazenada na 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')"

Note que usei $( ) em vez de backquotes, pois é geralmente preferido. Parece-me que você confundiu aspas 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, suponho que ${FOLDER} seja uma variável no computador local, portanto, isso precisa ser expandido imediatamente (e eu adicionei aspas simples ao redor, caso elas contenham espaços ou outros metacaracteres de shell); se for expandido pelo shell remoto, use \"\${FOLDER|/other_folder\" . Na verdade, colocar aspas simples em torno de ${FOLDER} não funcionará se contiver as própriaspas simples. Há uma maneira de consertar isso, mas não me incomodei aqui.

Você também pode usar aspas simples na atribuição de variável, mas, em seguida, teria problemas com as aspas simples no comando awk (não há uma maneira simples de aninhar aspas simples em uma cadeia de aspas simples ) e não há uma maneira limpa de expandir ${FOLDER} no computador local. Estes são solúveis com citações mistas, mas é confuso.

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

ssh -t user@server "$RM_CMD"

... isso não deve importar neste caso em particular, mas existem todos os tipos de coisas que podem dar errado com referências a variáveis sem aspas duplas, então geralmente é uma boa prática citá-las duas vezes

    
por 02.10.2016 / 21:50
2

Você pode verificar erros comuns em scripts bash com o ShellCheck , que funciona on-line, mas também está disponível como programa off-line . Suporta diferentes shells (identificadas pelo shebang) e também fornece avisos stylistik (como no seu caso usar $(...) em vez de backticks. Você também pode editar seu código colado e ver como ele é classificado (útil em combinação com tutoriais normais). no estilo de codificação).

    
por 30.09.2016 / 13:15