Помилка синтаксису біля несподіваного маркера `('


11

Коли я використовую код нижче в терміналі Ubuntu, він працює добре:

rm !(*.sh) -rf

Але якщо я поміщую той самий код рядка в сценарій оболонки (clean.sh) і запускаю скрипт оболонки з терміналу, він видає помилку:

сценарій clean.sh:

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

Я отримую помилку:

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

Ви можете допомогти?


Відповіді:


23

rm !(*.sh)є extglobсинтаксисом, який означає видалити всі файли, крім тих, у яких є .shрозширення.

У вашому інтерактивному bashекземплярі опція оболонки extglobувімкнена:

$ shopt extglob 
extglob         on

Тепер, коли ваш скрипт працює в передпласті, вам потрібно ввімкнути extglobйого, додавши це на початку сценарію:

shopt -s extglob

Отже, ваш сценарій виглядає так:

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

Редагувати:

Щоб видалити всі файли, окрім .shрозширень, використовуйте GLOBIGNORE(як ви не хочете вмикати extglob):

#!/bin/bash
GLOBIGNORE='*.sh'
rm -rf *

Приклад:

$ ls -1
barbar
bar.sh
egg
foo.sh
spam

$ GLOBIGNORE='*.sh'

$ rm *

$ ls -1
bar.sh
foo.sh

Чи можу я змінити свою команду, яка робить те ж саме, не запускаючи це? shopt -s extglob?
Тал

@Tal перевірити мої зміни ..
heemayl

1
спасибі :) (стек перевиконаний змушує мене написати 15 персонажів у коментарі :( :( :()
Тал

але ось два хороших відповіді!
Тал

1
Це має бути прийнятою відповіддю, оскільки вона насправді відповідає на питання, а інша лише описує обхід.
Гунтрам Блом підтримує Моніку

4

Гаразд, це перехресний пост, але я мушу написати відповідь. ;)

Ви можете використати findнатомість

find . -maxdepth 1 ! -name '*.sh' -exec rm -rf {} \;

2

Вам потрібно увімкнути extglob:

shopt -s extglob

1
@ Pilot6: Див man bash. Це дозволяє розширити глобус, як !(...).
choroba

Чи можу я змінити свою команду, яка робить те ж саме, не запускаючи це? shopt -s extglob
Тал
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.