I want to go through many directories and remove all the files except some that meet certain criterion. I have the following bash script:
#!/bin/bash
for i in */
do
cd $i
rm !(*M.*)
cd ..
done
However, when I run the script I get the following error:
script1.sh: line 5: syntax error near unexpected token `('
script1.sh: line 5: ` rm !(*M.*)'
What could be wrong? I'm using Ubuntu 14.04.
Thanks for your help.
I think you should enable extglob to use invert or negative wildcards:
shopt -s extglob
Note that you can keep this on all the time, it is not harmful.
That said, you are not forced to use a loop in your code and can directly put in your script:
rm */!(*M.*)
You can visit this post for other solutions:
https://unix.stackexchange.com/questions/78376/in-linux-how-to-delete-all-files-except-the-pattern-txt
Related
Question similar to here, but for my use case, I'd like to place inside the makefile.
#!/bin/bash
# Example:
# make run TEST_CASE="testbench.sv"
# make clean
compile:
vcs $(TEST_CASE) -sverilog;
run: compile
./simv
uvm_compile:
vcs $(TEST_CASE) -sverilog;
clean:
shopt -s extglob;
rm -v !(*.sv|*svh|"makefile");
The problem exist in make clean, and I got the following result:
ycliao#localhost:[~/workspace/i2c_vip/uvm_practice]: make clean
shopt -s extglob;
rm -v !(*.sv|*svh|"makefile");
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `rm -v !(*.sv|*svh|"makefile");'
make: *** [clean] Error 1
As I understand makefiles, every line is executed in a separate shell. So you need to add a line continuation to concatenate the commands so that they execute in the same shell:
SHELL = /bin/bash
# ...
clean:
shopt -s extglob; \
rm -v !(*.sv|*svh|"makefile");
This is demonstrated in Example makefiles on the wikipedia Make page.
I believe the problem is a bash problem. For some reason, it doesn't seem possible to do shopt followed by some command as a one-liner. Let's take make completely out of the picture. In a bash shell:
$ ls -1 /tmp/hosts.tar.*
/tmp/hosts.tar.bz2
/tmp/hosts.tar.gz
$ shopt -s extglob ; ls -1 /tmp/hosts.tar.#(bz2|gz)
bash: syntax error near unexpected token `('
$ ls -1 /tmp/hosts.tar.#(bz2|gz)
bash: syntax error near unexpected token `('
$ shopt -s extglob
$ ls -1 /tmp/hosts.tar.#(bz2|gz)
/tmp/hosts.tar.bz2
/tmp/hosts.tar.gz
To Sum up, for the makefile, it is not allow to have this.
ycliao#localhost:[~/workspace/i2c_vip/uvm_practice]: make clean
shopt -s extglob; \
rm -v !(*.sv|*svh|"makefile");
/bin/bash: -c: line 1: syntax error near unexpected token `('
/bin/bash: -c: line 1: `rm -v !(*.sv|*svh|"makefile");'
make: *** [clean] Error 1
The following command works perfectly when called directly from the terminal
scp -r ./!(node_modules|public) $SERVER:$WEBSITE_SRC
but when the same command is added to a shell script it fails with the following error
line 9: syntax error near unexpected token `('
here is the script for reference:
#!/bin/sh
set -e
SERVER=127.0.0.1
WEBSITE_SRC=~/website/src
echo "Deploying changes to the website src code"
scp ./.env* $SERVER:$WEBSITE_SRC
scp -r ./!(node_modules|public) $SERVER:$WEBSITE_SRC
!(node_modules|public) is extended globbing syntax. You should do two things.
Change the shebang line to #!/bin/bash to make sure your script is run by bash.
Put shopt -s extglob near the top to enable extended globbing syntax.
If it works interactively, it's probably because you have shopt -s extglob in one of your shell initialization files (e.g. ~/.bashrc).
I'm trying to run a script on a remote machine (both machines use bash), using ssh, which has the following lines:
cd /home/invitado/
rm -r !(Desktop|Downloads|Videos|Pictures)
So when I run ssh hostname './remove', I get this error:
syntax error near unexpected token `('
I tried appending this line to the script
shopt -s extglob
But I'm still having the same error, so what should I do? Thanks for your help.
shopt -s extglob should be before rm -r !(Desktop|Downloads|Videos|Pictures).
To verify, see what is the original value of extglob by running just shopt.
Note: In my case, that value was set when I run the command rm directly from the shell. But when I put it in script, it failed. Realized that extglob is set by default when running from interactive shell. & It is disabled by default when running inside the script.
I have a simple Makefile that just contains this one target. It looks like this:
SHELL:=/bin/bash
clean:
rm !(*.tex|Makefile|*.pdf)
When I run this command in bash it works fine, i.e. it gives no errors and it removes the desired files. However when I run make clean it gives the following errors:
$ make clean
rm !(*.tex|Makefile|*.pdf)
/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `rm !(*.tex|Makefile|*.pdf)'
make: *** [clean] Error 1
Has anybody got an idea what I'm doing wrong? Thanks.
Change the SHELL line to
SHELL:=/bin/bash -O extglob
The extglob option is not set by default, so you have to do that yourself.
I have a simple Makefile that just contains this one target. It looks like this:
SHELL:=/bin/bash
clean:
rm !(*.tex|Makefile|*.pdf)
When I run this command in bash it works fine, i.e. it gives no errors and it removes the desired files. However when I run make clean it gives the following errors:
$ make clean
rm !(*.tex|Makefile|*.pdf)
/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `rm !(*.tex|Makefile|*.pdf)'
make: *** [clean] Error 1
Has anybody got an idea what I'm doing wrong? Thanks.
Change the SHELL line to
SHELL:=/bin/bash -O extglob
The extglob option is not set by default, so you have to do that yourself.