Mar*_*ial 9 linux bash shell-script
脚本中写道:
rm -v !\(*.yaml\) ;\
Run Code Online (Sandbox Code Playgroud)
这会产生
rm: cannot remove '!(*.yaml)': No such file or directory
Run Code Online (Sandbox Code Playgroud)
但在命令行中工作正常。尝试过各种方式逃避:
rm -v !\(*.yaml\) ;\
Run Code Online (Sandbox Code Playgroud)
似乎无法找出适当的转义序列,我根本不明白。摆脱括号是我的第一步。然后试图逃跑!
,然后*
。还尝试使用反引号不转义,但出现错误“rm 缺少操作数”。我有点难住了。已经花了大约一个小时 - 只是“rm 所有内容而不是 yaml”...任何人都可以发现错误/建议修复吗?
我还尝试过#!/bin/sh 和#!/bin/bash。心想也许会有一些效果。
Sté*_*las 19
!(x)
是一个 Korn shell 全局运算符。支持 的glob 运算符bash
的子集,包括该运算符,但仅在\xc2\xb9之后ksh
shopt -s extglob
所以:
\nshopt -s extglob\nrm -f -- !(*.yaml)\n
Run Code Online (Sandbox Code Playgroud)\n将删除当前目录中的所有非隐藏文件,除了名称以.yaml
.
无论如何,全局运算符在引用时不会被识别,因此使用\\
(类似 Bourne 的 shell 中的引用运算符之一)不会有帮助。
shell中的等价物zsh
是:
rm -f -- ^*.yaml\n
Run Code Online (Sandbox Code Playgroud)\n为此,您需要set -o extendedglob
.
(它也支持or!(x)
之后)。emulate ksh
set -o kshglob
sh
尽管您可能会发现某些sh
实现,例如基于ksh
支持!(x)
作为扩展的实现,但该语言中没有等效的实现。
\xc2\xb9 由于它会影响 shell 语法解析,因此必须在读取和解析包含这些 ksh 扩展运算符之一的行之前shopt
执行该命令。例如,在 中,您会收到语法错误,因为首先解析整行(extglob 尚未打开),然后运行(好吧,如果没有语法错误,就会运行)。很好。bash -c 'shopt -s extglob; echo !(x)'
shopt
bash -O extglob -c 'echo !(x)'
Sot*_*oce 10
Bash 有一个功能,变量GLOBIGNORE
可以告诉 shell 从 glob 中删除哪些文件名,而剩下的文件名则需要进行操作(在本例中为rm -v
)。
这是一个演示:
mkdir /tmp/this-test
cd /tmp/this-test
touch one.yaml two.yaml three.json four.txt
echo *
Run Code Online (Sandbox Code Playgroud)
生产:
four.txt one.yaml three.json two.yaml
Run Code Online (Sandbox Code Playgroud)
现在设置GLOBIGNORE
忽略.yaml文件,然后禁用它的效果:
GLOBIGNORE='*.yaml'
echo *
GLOBIGNORE=
echo *
Run Code Online (Sandbox Code Playgroud)
生产:
four.txt three.json
four.txt one.yaml three.json two.yaml
Run Code Online (Sandbox Code Playgroud)
rm -v *
该命令echo *
将删除目录中名称不以.yaml
.
GLOBIGNORE
可以有一个 glob 表达式列表,每个表达式用冒号 ( :
) 分隔。例如,如果我 GLOBIGNORE='*.yaml:*.json'
在上面的演示中进行了设置,则该GLOBIGNORE
值将从 glob 列表中删除 .yaml 和 .json 文件名,因此只会four.txt
显示或删除该文件。