“rm -rf !(a)” 命令在 bash -c 语法中不起作用。

huangapple go评论72阅读模式
英文:

The command "rm -rf !(a)" doesn't work in bash -c syntax

问题

在家庭目录中有三个文件,分别命名为 'a'、'b' 和 'c'。我使用了 "rm -rf !(a)" 命令来删除 'b' 和 'c' 文件,在 bash 命令行中运行时,它正常工作。如下所示:

xx@xx:~/# ls
a b c
xx@xx:~/# rm -rf !(a)
xx@xx:~/# ls
a

然而,当我使用 "bash -c" 来运行它时,它给我报了一个语法错误,如下所示:

xx@xx:~/# ls
a b c
xx@xx:~/# bash -c "rm -rf !(a)"
bash: -c: line 0: syntax error near unexpected token '('
bash: -c: line 0: 'rm -rf !(a)'

然后我在 '!'、'(' 和 ')' 前面添加了反斜杠符号 ''。尽管没有错误发生,但我发现它不起作用。如下所示:

xx@xx:~/# ls
a b c
xx@xx:~/# bash -c "rm -rf \!(a)"
xx@xx:~/# ls
a b c

有人能帮忙澄清这个问题吗?

英文:

There are three files in family dir named 'a' 'b' 'c'. I used "rm -rf !(a)" to delete the 'b' and 'c' files, after run it in bash CLI, it worked fine. As below:

xx@xx:~/# ls
a b c
xx@xx:~/# rm -rf !(a)
xx@xx:~/# ls
a

However, when I was running it by "bash -c", it threw a syntax error to me, that is as below:[![enter image description here]

xx@xx:~/# ls
a b c
xx@xx:~/# bash -c "rm -rf !(a)"
bash: -c: line 0: syntax error near unexpected token`('
bash: -c: line 0:`rm -rf !(a)'

Then I added backslash before '!', '(' and ')'. Although, there is not error occur; I found it did not work. As below:

xx@xx:~/# ls
a b c
xx@xx:~/# bash -c "rm -rf \!\(a\)"
xx@xx:~/# ls
a b c

Could any body can help to clarify this problem?

答案1

得分: 5

不要滥用 extglob 模式。
不要滥用“not”逻辑。
不要滥用 globs

请千万不要在 root 用户下除了几乎是极度谨慎的情况下,使用 rm -fr 删除任何东西。

如果在该目录或其任何子目录中有除了 a 以外的任何内容,都将被删除。

如有需要,可以提出进一步问题。

英文:

Don't use extglob patterns carelessly.
Don't use "not" logic carelessly.
Don't use globs carelessly.

And for all gods' sake, please don't use rm -fr as root with anything other than damned-near paranoia.

If you had anything besides a in that directory, or in any subdirectory of it, it's gone.

$: find
.
./a
./abc
./bar
./bcd
./efg
./efg/hij
./efg/hij/klm
./foo
./x
./y
./y/deleteme
./y/deleteme/stuff

$: bash -O extglob -c 'echo rm -fr !(x)'
rm -fr a abc bar bcd efg foo y

Obviously, it grabs everything that is, as you asked, not x.
As Ted Lyngmo pointed out in his comment above,
> rm -rf [^a] would do if you want to remove all one letter files and directories except a. If you want to remove b and c explicitly: rm -rf [bc] ... or rm -rf b c ...

Simple, clear, and specific is virtually always better when it's an option.

Added by Ted:


> If you want to remove all files except b and c in the current directory (which is what you asked for in a comment) you could again use find with the extension -maxdepth 1 to only make it search in the current directory:

find . -maxdepth 1 -type f \! \( -name b -o -name c \) -exec echo {} +

> Replace echo with rm -f if you are sure you want to delete those listed. The find version included in [tag:linux] has some more extensions making it possible to skip providing the top directory . and it also has a -delete option to delete files:

# danger zone below:
find -maxdepth 1 -type f \! \( -name b -o -name c \) -delete

(Thanks, Ted - I was just coming back to add this, lol)

> Paul Hodegs, you are right, however there is a case that i need keep some specified file or sub-dir in a certain dir, we need to remove the other dirty data in this dir regularly to avoid limited disk no-free case caused by some partners forgetting remove his/her research data in this dir after he or she used. –
Yayong Duan

Valid, in which case your original question is (sort of) a programming question. Be very careful to always assert that you are working in/on the right directory, and careful that maybe you back up your data pretty often against possible errors, but the important thing in that case is that you explicitly list ALL the files you want to keep in the single command to remove everything else.

In my above example, if you wanted to keep abc and bcd, you'd need rm -fr $thatDir/!(abd|bcd).

Just be super careful with that, and I strongly suggest using a nonprivileged user.

huangapple
  • 本文由 发表于 2023年7月6日 21:36:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76629433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定