1

bash on mac, installed by brew

λ  brew list | grep bash
bash

λ  which bash
/usr/local/bin/bash
λ  rm !("shorturl.api")
-bash: !: event not found
λ  ls -1 | grep -v shorturl.api | xargs rm
rm: cannot remove ''$'\033''[0m'$'\033''[01;32mapi'$'\033''[0m': No such file or directory
rm: cannot remove ''$'\033''[01;34metc'$'\033''[0m': No such file or directory
rm: cannot remove ''$'\033''[01;34minternal'$'\033''[0m': No such file or directory
rm: cannot remove ''$'\033''[00mshorturl.go'$'\033''[0m': No such file or directory

Antonio Petricca
  • 8,891
  • 5
  • 36
  • 74
dfang
  • 1,366
  • 15
  • 41
  • 1
    Just because it would run `/usr/local/bin/bash` if you typed `bash`, that does not mean you are currently running `/usr/local/bin/bash`. The shell you are running might have been started by running something other than `bash`. – Mark Setchell Mar 22 '22 at 08:10
  • 2
    Your filenames look like they contain colour escape sequences, because you have parsed the output of `ls` which is a *"bad idea"* **TM**. – Mark Setchell Mar 22 '22 at 08:11
  • 1
    The negative wildcard pattern requires extended globbing syntax (`shopt extglob`); see ["How can I use inverse or negative wildcards when pattern matching in a unix/linux shell?"](https://stackoverflow.com/questions/216995) In the `ls` version, you apparently have `ls` set to output in color, and so the color escape sequences are messing things up; see ["Extra escape characters from `ls` command making life hard"](https://stackoverflow.com/questions/55634528). This is one of many things that can go wrong parsing the output of `ls`, so [don't do that](http://mywiki.wooledge.org/ParsingLs). – Gordon Davisson Mar 22 '22 at 09:36
  • @MarkSetchell my login shell is bash, echo $SHELL is /usr/local/bin/bash. – dfang Mar 23 '22 at 11:57
  • thanks @GordonDavisson, now i know where these escape characters from and how to turn if off – dfang Mar 23 '22 at 12:05

2 Answers2

1

The !(pattern-list) globbing pattern only works when extended globbing is enabled. See the extglob section in glob - Greg's Wiki. In this case you need:

shopt -s extglob
rm -- !(shorturl.api)
  • The -- with rm is to prevent files whose names begin with - being treated as options.

One way to do it without extended globbing is:

find . -maxdepth 1 -type f ! -name shorturl.api -delete

The ls -1 | grep -v shorturl.api | xargs rm attempt in the question is broken in several ways, including:

  • The output of ls is intended for reading by humans. It is not suitable for automatic processing. See Why you shouldn't parse the output of ls(1).
  • The grep -v shorturl.api will exclude files other than the intended one. For instance, old-shorturl.api would be excluded.
  • xargs by default uses spaces and newlines to split its input into arguments. xargs rm won't delete files that have such characters in their names.
pjh
  • 6,388
  • 2
  • 16
  • 17
  • what a pity that ls output is not suitable for xargs processing – dfang Mar 23 '22 at 11:56
  • @dfang, agreed. See [Is there a reason why ls does not have a --zero or -0 option](https://unix.stackexchange.com/q/112125) for more information. `find` is much better for listing and filtering anyway, but sorting the output of `find` according to time or size etc. is tricky to do correctly. – pjh Mar 23 '22 at 13:57
-1

thanks @GordonDavisson.

use ls --color before pipeline to xargs

ls -1 --color=never | grep -v shorturl.api | xargs rm -rf
dfang
  • 1,366
  • 15
  • 41