! (*. sh) funciona na linha de comando, mas não em um script

2

Quando eu uso o código abaixo em um terminal no Ubuntu, ele funciona bem:

rm !(*.sh) -rf

Mas se eu colocar o mesmo código de linha em um script de shell ( clean.sh ) e executar o shell script do terminal, ele lançará um erro como este

script clean.sh:

#!/bin/bash
rm !(*.sh) -rf

Erro que recebo:

./clean.sh: line 2: syntax error near unexpected token '('
./clean.sh: line 2: 'rm !(*.sh) -rf'

você pode ajudar?

    
por Tal 04.08.2015 / 12:35

3 respostas

1

Abordagem Shell Script

Por padrão, globs não funcionam em um script BASH (embora você possa ativá-los com shopt ). Se o script de shell for executado por um interpretador não-BASH, os globs podem não funcionar.

Você pode obter o mesmo efeito usando o comando find , que é como eu recomendaria fazê-lo (por causa de quanto mais controle você pode ter quando os requisitos aumentarem).

Experimente o tamanho: find . -mindepth 1 -maxdepth 1 -not -iname "*.sh" -exec rm -rf {} \;

Abordagem do Makefile

Outra abordagem que você poderia adotar:

Se você está fazendo algo que quer ser limpo depois, há uma boa chance de que um Makefile seja a ferramenta certa para o trabalho, em vez de um monte de clean.sh, build.sh, install.sh, etc.

Isso é especialmente verdadeiro se você quiser garantir que suas receitas sempre aconteçam em ordem ou se nem sempre quiser executar novamente as receitas que produzem uma saída.

Um Makefile simples que fazia a mesma coisa ficaria assim:
(note que o espaço em branco antes de rm precisa ser uma tabulação porque é assim que os rolos são feitos)

SOURCES := $(wildcard *.sh)
CLEAN_FILES := $(filter-out $(SOURCES),$(wildcard *))
CLEAN_FILES := $(filter-out Makefile,$(CLEAN_FILES))

build: $(SOURCES)
    YOUR_RECIPE_HERE

clean:
    rm -rf $(CLEAN_FILES)
    
por 05.08.2015 / 07:56
4

Você precisa transformar extglob em:

shopt -s extglob
    
por 04.08.2015 / 12:44
1

No bash, determinados padrões não são ativados por padrão, mas podem ser ativada definindo uma opção com shopt . Os padrões !(NOT-THIS) , @(THIS|THAT) , *(ZERO-OR-MORE) , +(ONE-OR-MORE) e ?(OPTIONAL) , que não existiam nos shells iniciais do Unix, foram posteriormente adicionados em ksh e não são padronizados pelo POSIX, não são reconhecidos por Por padrão, você precisa executar shopt -s extglob primeiro.

Você pode usar esses padrões na linha de comando; isso indica que você tem shopt -s extglob no seu .bashrc . Esse arquivo é lido apenas por shells interativos, não por scripts.

(Se a variável de ambiente BASH_ENV for definida quando o bash começar a executar um script, o bash lerá o arquivo que ele designar, mas eu não recomendo contar com isso, pois isso faria com que seu script funcionasse somente quando BASH_ENV é definido com o valor que você espera e somente se você não alterar o arquivo para o qual ele aponta.)

Inclua apenas shopt -s extglob na parte superior do script, abaixo da linha #!/bin/bash .

    
por 05.08.2015 / 10:17